home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / ck5a189s / ckutio.c < prev    next >
C/C++ Source or Header  |  1993-07-08  |  207KB  |  6,805 lines

  1. char *ckxv = "UNIX Communications support, 5A(110), 26 Jun 93";
  2.  
  3. /*  C K U T I O  */
  4.  
  5. /* C-Kermit interrupt, terminal control & i/o functions for UNIX */
  6.  
  7. /*
  8.   Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
  9.   Columbia University Academic Information Systems, New York City.
  10.  
  11.   Copyright (C) 1985, 1993, Trustees of Columbia University in the City of New
  12.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  13.   sold for profit as a software product itself, nor may it be included in or
  14.   distributed with commercial products or otherwise distributed by commercial
  15.   concerns to their clients or customers without written permission of the
  16.   Office of Kermit Development and Distribution, Columbia University.  This
  17.   copyright notice must not be removed, altered, or obscured.
  18. */
  19.  
  20. /* Includes */
  21.  
  22. #include "ckcdeb.h"            /* This moved to here. */
  23. #include <errno.h>            /* System error numbers */
  24. #ifdef __386BSD__
  25. #define ENOTCONN 57
  26. #endif /* __386BSD__ */
  27.  
  28. #include "ckcnet.h"            /* Symbols for network types. */
  29.  
  30. /*
  31.   The directory-related includes are here because we need to test some
  32.   file-system-related symbols to find out which system we're being compiled
  33.   under.  For example, MAXNAMLEN is defined in BSD4.2 but not 4.1.
  34. */
  35. #ifdef SDIRENT                /* Directory bits... */
  36. #define DIRENT
  37. #endif /* SDIRENT */
  38.  
  39. #ifdef XNDIR
  40. #include <sys/ndir.h>
  41. #else /* !XNDIR */
  42. #ifdef NDIR
  43. #include <ndir.h>
  44. #else /* !NDIR, !XNDIR */
  45. #ifdef RTU
  46. #include "/usr/lib/ndir.h"
  47. #else /* !RTU, !NDIR, !XNDIR */
  48. #ifdef DIRENT
  49. #ifdef SDIRENT
  50. #include <sys/dirent.h>
  51. #else
  52. #include <dirent.h>
  53. #endif /* SDIRENT */
  54. #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
  55. #include <sys/dir.h>
  56. #endif /* DIRENT */
  57. #endif /* RTU */
  58. #endif /* NDIR */
  59. #endif /* XNDIR */
  60.  
  61. /* Definition of HZ, used in msleep() */
  62.  
  63. #ifdef MIPS
  64. #define HZ ( 1000 / CLOCK_TICK )
  65. #else
  66. #ifdef ATTSV
  67. #ifndef NAP
  68. #ifndef TRS16
  69. #include <sys/param.h>
  70. #else
  71. #define HZ ( 1000 / CLOCK_TICK )
  72. #endif /* TRS16 */
  73. #ifdef NAPHACK
  74. #define nap(x) (void)syscall(3112, (x))
  75. #define NAP
  76. #endif /* NAPHACK */
  77. #endif /* NAP */
  78. #endif /* ATTSV */
  79. #endif /* MIPS */
  80.  
  81. #ifdef M_UNIX
  82. #undef NGROUPS_MAX        /* Prevent multiple definition warnings */
  83. #endif /* M_UNIX */
  84.  
  85. #ifdef CK_POLL
  86. #ifndef AIXRS            /* IBM AIX needs special handling */
  87. #include <poll.h>        /* "standard" (SVID) i/o multiplexing, etc */
  88. #else /* AIXRS */
  89. #ifdef SVR4            /* AIX 3.2 is like SVID... */
  90. #include <poll.h>
  91. #else                /* But AIX 3.1 is not ... */
  92. #include <sys/poll.h>        /* The include file is in include/sys */
  93. #define events reqevents    /* And it does not map IBM-specific member */
  94. #define revents rtnevents    /* names to the System V equivalents */
  95. #endif /* SVR4 */
  96. #endif /* AIXRS */
  97. #endif /* CK_POLL */
  98.  
  99. #include <signal.h>                     /* Signals */
  100.  
  101. /* For setjmp and longjmp */
  102.  
  103. #ifndef ZILOG
  104. #include <setjmp.h>
  105. #else
  106. #include <setret.h>
  107. #endif /* ZILOG */
  108.  
  109. /* Maximum length for the name of a tty device */
  110.  
  111. #ifndef DEVNAMLEN
  112. #define DEVNAMLEN 25
  113. #endif /* DEVNAMLEN */
  114.  
  115. #ifdef    NETCONN
  116. #undef DEVNAMLEN
  117. #define DEVNAMLEN 50            /* longer field for host:service */
  118. #endif  /* NETCONN */
  119.  
  120. /*
  121.   The following test differentiates between 4.1 BSD and 4.2 & later.
  122.   If you have a 4.1BSD system with the DIRENT library, this test could
  123.   mistakenly diagnose 4.2BSD and then later enable the use of system calls
  124.   that aren't defined.  If indeed there are such systems, we can use some
  125.   other way of testing for 4.1BSD, or add yet another compile-time switch.
  126. */  
  127. #ifdef BSD4
  128. #ifdef MAXNAMLEN
  129. #ifndef FT21
  130. #ifndef FT18                /* Except for Fortune. */
  131. #define BSD42
  132. #endif /* FT18 */
  133. #endif /* FT21 */
  134. #endif /* MAXNAMLEN */
  135. #endif /* BSD4 */
  136. /*
  137.  MINIX 1.0 support added by Charles Hedrick,
  138.  Rutgers University <hedrick@aramis.rutgers.edu>.
  139.  MINIX also has V7 enabled.
  140. */
  141. #ifdef MINIX
  142. #define TANDEM 0
  143. #define MYREAD
  144. #include <limits.h>
  145. #endif /* MINIX */
  146.  
  147. #include "ckuver.h"            /* Version herald */
  148. char *ckxsys = HERALD;
  149.  
  150. /* UUCP lock file name definition */
  151.  
  152. #ifndef NOUUCP
  153.  
  154. /* Name of UUCP tty device lock file */
  155.  
  156. #ifdef ACUCNTRL
  157. #define LCKDIR
  158. #endif /* ACUCNTRL */
  159. /*
  160.   LOCK_DIR is the name of the lockfile directory.
  161.   If LOCK_DIR is already defined (e.g. on command line), we don't change it.
  162.   PIDSTRING means use ASCII string to represent pid in lockfile.
  163. */
  164. #ifndef LOCK_DIR
  165. #ifdef BSD44
  166. #define LOCK_DIR "/var/spool/uucp";
  167. #else
  168. #ifdef DGUX430
  169. #define LOCK_DIR "/var/spool/locks";
  170. #else
  171. #ifdef RTAIX                /* IBM RT PC AIX 2.2.1 */
  172. #define PIDSTRING
  173. #define LOCK_DIR "/etc/locks";
  174. #else
  175. #ifdef AIXRS
  176. #define PIDSTRING
  177. #define LOCK_DIR "/etc/locks";
  178. #else
  179. #ifdef ISIII
  180. #define LOCK_DIR "/etc/locks";
  181. #else
  182. #ifdef HDBUUCP
  183. #define PIDSTRING
  184. #ifdef M_SYS5  /* wht@n4hgf - SCO */
  185. #define LOCK_DIR "/usr/spool/uucp";
  186. #else
  187. #ifdef M_UNIX
  188. #define LOCK_DIR "/usr/spool/uucp";
  189. #else
  190. #ifdef SVR4
  191. #define LOCK_DIR "/var/spool/locks";
  192. #ifndef LOCKF
  193. #define LOCKF                /* Use lockf() too in SVR4 */
  194. #endif /* LOCKF */
  195. #else
  196. #ifdef SUNOS4
  197. #define LOCK_DIR "/var/spool/locks";
  198. #else
  199. #define LOCK_DIR "/usr/spool/locks";
  200. #endif /* SUNOS4 */
  201. #endif /* SVR4 */
  202. #endif /* M_UNIX */
  203. #endif /* M_SYS5 */
  204. #else
  205. #ifdef LCKDIR
  206. #define LOCK_DIR "/usr/spool/uucp/LCK";
  207. #else
  208. #ifdef COHERENT
  209. #define LOCK_DIR "/usr/spool/uucp";
  210. #define PIDSTRING
  211. #else
  212. #define LOCK_DIR "/usr/spool/uucp";
  213. #endif /* COHERENT */
  214. #endif /* LCKDIR */
  215. #endif /* HDBUUCP */
  216. #endif /* ISIII */
  217. #endif /* AIXRS */
  218. #endif /* RTAIX */
  219. #endif /* DGUX430 */
  220. #endif /* BSD44 */
  221. #endif /* !LOCK_DIR (outside ifndef) */
  222.    
  223. #endif /* !NOUUCP */
  224.  
  225. #ifdef ATTSV
  226. #define MYREAD
  227. #endif /* ATTSV */
  228.  
  229. #ifdef ATT7300
  230. #ifndef MYREAD
  231. #define MYREAD
  232. #endif /* MYREAD */
  233. /* bits for attmodem: internal modem in use, restart getty */
  234. #define ISMODEM 1
  235. #define DOGETY 512
  236. #endif  /* ATT7300 */
  237.  
  238. #ifdef BSD42
  239. #define MYREAD
  240. #endif /* BSD42 */
  241.  
  242. #ifdef POSIX
  243. #define MYREAD
  244. #endif /* POSIX */
  245.  
  246. /*
  247.  Variables available to outside world:
  248.  
  249.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  250.    dfloc  -- 0 if dftty is console, 1 if external line.
  251.    dfprty -- Default parity
  252.    dfflow -- Default flow control
  253.    ckxech -- Flag for who echoes console typein:
  254.      1 - The program (system echo is turned off)
  255.      0 - The system (or front end, or terminal).
  256.    functions that want to do their own echoing should check this flag
  257.    before doing so.
  258.  
  259.    flfnam  -- Name of lock file, including its path, e.g.,
  260.                 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
  261.    lkflfn  -- Name of link to lock file, including its paths
  262.    haslock -- Flag set if this kermit established a uucp lock.
  263.    backgrd -- Flag indicating program executing in background ( & on
  264.                 end of shell command). Used to ignore INT and QUIT signals.
  265.    rtu_bug -- Set by stptrap().  RTU treats ^Z as EOF (but only when we handle
  266.                 SIGTSTP)
  267.  
  268.  Functions for assigned communication line (either external or console tty):
  269.  
  270.    sysinit()               -- System dependent program initialization
  271.    syscleanup()            -- System dependent program shutdown
  272.    ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
  273.    ttclos()                -- Close & reset the tty, releasing any access lock.
  274.    ttsspd(cps)             -- Set the transmission speed of the tty.
  275.    ttgspd()                -- Get (read) the the transmission speed of the tty.
  276.    ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
  277.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  278.                                 or in DIALING or CONNECTED modem control state.
  279.    ttres()                 -- Restore original tty modes.
  280.    ttscarr(carrier)        -- Set carrier control mode, on/off/auto.
  281.    ttinl(dest,max,timo)    -- Timed read line from the tty.
  282.    ttinc(timo)             -- Timed read character from tty.
  283.    myread()                -- Raw mode bulk buffer read, gives subsequent
  284.                                 chars one at a time and simulates FIONREAD.
  285.    myunrd(c)               -- Places c back in buffer to be read (one only)
  286.    ttchk()                 -- See how many characters in tty input buffer.
  287.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  288.    ttol(string,length)     -- Write a string to the tty.
  289.    ttoc(c)                 -- Write a character to the tty.
  290.    ttflui()                -- Flush tty input buffer.
  291.    ttsndb()                -- Send BREAK signal.
  292.    ttsndlb()               -- Send Long BREAK signal.
  293.  
  294.    ttlock(ttname)          -- "Lock" tty device against uucp collisions.
  295.    ttunlck()               -- Unlock tty device.
  296.  
  297.                               For ATT7300/Unix PC, System V:
  298.    attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
  299.    offgetty(ttname)        -- Turns off getty(1m) for comms line
  300.    ongetty(ttname)         -- Restores getty() to comms line
  301. */
  302.  
  303. /*
  304. Functions for console terminal:
  305.  
  306.    congm()   -- Get console terminal modes.
  307.    concb(esc) -- Put the console in single-character wakeup mode with no echo.
  308.    conbin(esc) -- Put the console in binary (raw) mode.
  309.    conres()  -- Restore the console to mode obtained by congm().
  310.    conoc(c)  -- Unbuffered output, one character to console.
  311.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  312.    conola(s) -- Unbuffered output, array of strings to the console.
  313.    conxo(n,s) -- Unbuffered output, n characters to the console.
  314.    conchk()  -- Check if characters available at console (bsd 4.2).
  315.                 Check if escape char (^\) typed at console (System III/V).
  316.    coninc(timo)  -- Timed get a character from the console.
  317.    congks(timo)  -- Timed get keyboard scan code.
  318.    conint()  -- Enable terminal interrupts on the console if not background.
  319.    connoi()  -- Disable terminal interrupts on the console if not background.
  320.  
  321. Time functions
  322.  
  323.    msleep(m) -- Millisecond sleep
  324.    ztime(&s) -- Return pointer to date/time string
  325.    rtimer() --  Reset timer
  326.    gtimer()  -- Get elapsed time since last call to rtimer()
  327. */
  328.  
  329. /* Conditional Includes */
  330.  
  331. /* Whether to include <sys/file.h> */
  332.  
  333. #ifdef RTU                /* RTU doesn't */
  334. #define NOFILEH
  335. #endif /* RTU */
  336.  
  337. #ifdef CIE                /* CIE does. */
  338. #undef NOFILEH
  339. #endif /* CIE */
  340.  
  341. #ifdef BSD41                /* 4.1 BSD doesn't */
  342. #define NOFILEH
  343. #endif /* BSD41 */
  344.  
  345. #ifdef is68k                /* is68k (whatever that is)  */
  346. #define NOFILEH
  347. #endif /* is68k */
  348.  
  349. #ifdef MINIX                /* MINIX */
  350. #define NOFILEH
  351. #endif /* MINIX */
  352.  
  353. #ifdef COHERENT                /* Coherent */
  354. #define NOFILEH
  355. #endif /* COHERENT */
  356.  
  357. #ifndef NOFILEH                /* Now include if selected. */
  358. #include <sys/file.h>
  359. #endif /* NOFILEH */
  360.  
  361. /* POSIX */
  362.  
  363. #ifdef BSD44ORPOSIX            /* POSIX uses termios.h */
  364. #define TERMIOS
  365. #ifdef bsdi
  366. #ifndef NCCS
  367. #define NCCS 20
  368. #endif /* NCCS */
  369. #endif /* bsdi */
  370. #include <termios.h>
  371. #ifndef BSD44                /* Really POSIX */
  372. #define NOSYSIOCTLH            /* No ioctl's allowed. */
  373. #undef ultrix                /* Turn off any ultrix features. */
  374. #endif /* BSD44 */
  375. #endif /* POSIX */
  376.  
  377. /* System III, System V */
  378.  
  379. #ifdef ATTSV
  380. #ifndef BSD44
  381. #include <termio.h>
  382. #endif /* BSD44 */
  383. #ifdef SVR4                /* Sys V R4 and later */
  384. #ifdef TERMIOX
  385. /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
  386. #include <termiox.h>
  387.   struct termiox rctsx;
  388. #else
  389. #ifdef STERMIOX
  390. #include <sys/termiox.h>
  391.   struct termiox rctsx;
  392. #endif /* STERMIOX */
  393. #endif /* TERMIOX */
  394. #endif /* SVR4 */
  395. #endif /* ATTSV */
  396.  
  397. #ifdef MINIX                /* MINIX uses ioctl's */
  398. #define NOSYSIOCTLH            /* but has no <sys/ioctl.h> */
  399. #endif /* MINIX */
  400.  
  401. /* Others */
  402.  
  403. #ifndef NOSYSIOCTLH            /* Others use ioctl() */
  404. #ifdef SUN4S5
  405. /*
  406.   This is to get rid of cpp warning messages that occur because all of
  407.   these symbols are defined by both termios.h and ioctl.h on the SUN.
  408. */
  409. #undef ECHO
  410. #undef NL0
  411. #undef NL1
  412. #undef TAB0
  413. #undef TAB1
  414. #undef TAB2
  415. #undef XTABS
  416. #undef CR0
  417. #undef CR1
  418. #undef CR2
  419. #undef CR3
  420. #undef FF0
  421. #undef FF1
  422. #undef BS0
  423. #undef BS1
  424. #undef TOSTOP
  425. #undef FLUSHO
  426. #undef PENDIN
  427. #undef NOFLSH
  428. #endif /* SUN4S5 */
  429. #include <sys/ioctl.h>
  430. #endif /* NOSYSIOCTLH */
  431.  
  432. /* Whether to include <fcntl.h> */
  433.  
  434. #ifndef is68k                /* Only a few don't have this one. */
  435. #ifndef BSD41
  436. #ifndef FT21
  437. #ifndef FT18
  438. #ifndef COHERENT
  439. #include <fcntl.h>
  440. #endif /* COHERENT */
  441. #endif /* FT18 */
  442. #endif /* FT21 */
  443. #endif /* BSD41 */
  444. #endif /* not is68k */
  445.  
  446. #ifdef COHERENT
  447. #ifdef _I386
  448. #include <fcntl.h>
  449. #else
  450. #include <sys/fcntl.h>
  451. #endif /* _I386 */
  452. #endif /* COHERENT */
  453.  
  454. #ifdef ATT7300                /* Unix PC, internal modem dialer */
  455. #include <sys/phone.h>
  456. #endif /* ATT7300 */
  457.  
  458. #ifdef HPUX                /* HP-UX variations. */
  459. #define HPUXJOBCTL
  460. #include <sys/modem.h>            /* HP-UX modem signals */
  461. #ifdef hp9000s500            /* Model 500 */
  462. #undef HPUXJOBCTL
  463. #endif /* hp9000s500 */
  464. #ifdef HPUXPRE65
  465. #undef HPUXJOBCTL
  466. typedef int mflag;
  467. #endif /* HPUXPRE65 */
  468. #ifdef HPUXJOBCTL
  469. #include <sys/bsdtty.h>            /* HP-UX Berkeley tty support */
  470. #endif /* HPUXJOBCTL */
  471. #endif /* HPUX */
  472.  
  473. /* BSD, V7, Coherent, Minix, et al. */
  474.  
  475. #ifdef SVORPOSIX            /* Sys V or POSIX */
  476. #ifdef OXOS
  477. #include <sys/time.h>
  478. #endif /* OXOS */
  479. #ifdef BSD44
  480. #include <sys/time.h>
  481. #endif /* BSD44 */
  482. #ifdef AIXRS
  483. #include <sys/time.h>
  484. #endif /* AIXRS */
  485. #ifdef NOIEXTEN                /* This is broken on some systems */
  486. #undef IEXTEN                /* like Convex/OS 9.1 */
  487. #endif /* NOIEXTEN */
  488. #ifndef IEXTEN                /* Turn off ^O/^V processing. */
  489. #define IEXTEN 0            /* Needed, at least, on BSDI. */
  490. #endif /* IEXTEN */
  491. #else                    /* Not AT&T Sys V or POSIX */
  492. #include <sgtty.h>                      /* So we use <sgtty.h> */
  493. #ifndef PROVX1                /* Now <sys/time.h> ... */
  494. #ifndef V7
  495. #ifndef BSD41
  496. #ifndef COHERENT
  497. #include <sys/time.h>                   /* Clock info (for break generation) */
  498. #endif /* COHERENT */
  499. #endif /* BSD41 */
  500. #endif /* V7 */
  501. #endif /* PROVX1 */
  502. #endif /* SVORPOSIX */
  503.  
  504. #ifdef PS2AIX10
  505. #include <sys/time.h>                   /* Clock info for PS/2 AIX 1.x */
  506. #endif /* PS2AIX10 */
  507.  
  508. #ifdef OSF                /* DEC OSF/1 1.0 */
  509. #include <sys/timeb.h>
  510. #endif /* OSF */
  511.  
  512. #ifdef QNX
  513. #include <sys/timeb.h>            /* QNX 4.1 */
  514. #endif /* QNX */
  515.  
  516. #ifdef BSD41                /* BSD 4.1 */
  517. #include <sys/timeb.h>
  518. #endif /* BSD41 */
  519.  
  520. #ifdef FT21                /* For:Pro 2.1 */
  521. #include <sys/timeb.h>
  522. #endif /* FT21 */
  523.  
  524. #ifdef BSD29                /* BSD 2.9 */
  525. #include <sys/timeb.h>
  526. #endif /* BSD29 */
  527.  
  528. #ifdef TOWER1
  529. #include <sys/timeb.h>                  /* Clock info for NCR Tower */
  530. #endif /* TOWER1 */
  531.  
  532. #ifdef COHERENT
  533. #include <sys/timeb.h>                  /* Clock info for NCR Tower */
  534. #endif /* COHERENT */
  535.  
  536. #ifdef aegis
  537. #include "/sys/ins/base.ins.c"
  538. #include "/sys/ins/error.ins.c"
  539. #include "/sys/ins/ios.ins.c"
  540. #include "/sys/ins/sio.ins.c"
  541. #include "/sys/ins/pad.ins.c"
  542. #include "/sys/ins/time.ins.c"
  543. #include "/sys/ins/pfm.ins.c"
  544. #include "/sys/ins/pgm.ins.c"
  545. #include "/sys/ins/ec2.ins.c"
  546. #include "/sys/ins/type_uids.ins.c"
  547. #include <default_acl.h>
  548. #undef TIOCEXCL
  549. #undef FIONREAD
  550. #endif /* aegis */
  551.  
  552. #ifdef sxaE50                /* PFU Compact A SX/A TISP V10/L50 */
  553. #undef FIONREAD
  554. #endif /* sxaE50 */
  555.  
  556. /* The following #defines are catch-alls for those systems */
  557. /* that didn't have or couldn't find <file.h>... */
  558.  
  559. #ifndef FREAD
  560. #define FREAD 0x01
  561. #endif /* FREAD */
  562.  
  563. #ifndef FWRITE
  564. #define FWRITE 0x10
  565. #endif /* FWRITE */
  566.  
  567. #ifndef O_RDONLY
  568. #define O_RDONLY 000
  569. #endif /* O_RDONLY */
  570.  
  571. /* Declarations */
  572.  
  573. #ifdef OXOS
  574. #undef TCGETA
  575. #undef TCSETA
  576. #undef TCSETAW
  577. #undef TCSETAF
  578. #define TCGETA TCGETS
  579. #define TCSETA TCSETS
  580. #define TCSETAW TCSETSW
  581. #define TCSETAF TCSETSF
  582. #define termio termios
  583. #endif /* OXOS */
  584.  
  585. #ifdef _POSIX_SOURCE            /* This includes MINIX */
  586. #ifndef AIXRS
  587. #include <time.h>
  588. #endif /* AIXRS */
  589. #ifdef __GNUC__
  590. #ifdef XENIX
  591. /*
  592.   Because Xenix <time.h> doesn't declare time() if we're using gcc.
  593. */
  594. time_t time();
  595. #endif /* XENIX */
  596. #endif /* __GNUC__ */
  597. #else
  598. time_t time();                /* All Unixes should have this... */
  599. #endif /* _POSIX_SOURCE */
  600.  
  601. /* Special stuff for V7 input buffer peeking */
  602.  
  603. #ifdef  V7
  604. int kmem[2] = { -1, -1};
  605. char *initrawq(), *qaddr[2]={0,0};
  606. #define CON 0
  607. #define TTY 1
  608. #endif /* V7 */
  609.  
  610. /* dftty is the device name of the default device for file transfer */
  611. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  612.  
  613. #ifndef DFTTY
  614. #ifdef PROVX1
  615.     char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
  616.     char *dfmdm = "none";
  617.     int dfloc = 1;                  /* that goes in local mode by default */
  618. #else
  619. #ifdef COHERENT
  620.     char *dftty = "/dev/modem";
  621.     char *dfmdm = "none";
  622.     int dfloc = 1;
  623. #else
  624.     char *dftty = CTTNAM;               /* Remote by default, use normal */
  625.     char *dfmdm = "none";
  626.     int dfloc = 0;                      /* controlling terminal name. */
  627. #endif /* COHERENT */
  628. #endif /* PROVX1 */
  629. #else
  630.     char *dftty = DFTTY;        /* Default location specified on */
  631.     char *dfmdm = "none";        /* command line. */
  632.     int dfloc = 1;                      /* controlling terminal name. */
  633. #endif /* DFTTY */
  634.  
  635. #ifdef RTU
  636.     int rtu_bug = 0;            /* set to 1 when returning from SIGTSTP */
  637. #endif /* RTU */
  638.  
  639.     int dfprty = DEFPAR;                /* Default parity (0 = none) */
  640.     int ttprty = 0;                     /* The parity that is in use. */
  641.     int ttpflg = 0;            /* Parity not sensed yet. */
  642.     static int ttpmsk = 0377;        /* Parity stripping mask. */
  643.     int ttmdm = 0;                      /* Modem in use. */
  644.     int ttcarr = CAR_AUT;        /* Carrier handling mode. */
  645.     int dfflow = FLO_XONX;        /* Default is Xon/Xoff */
  646.     int backgrd = 0;                    /* Assume in foreground (no '&' ) */
  647. #ifdef ultrix
  648.     int iniflags = 0;            /* fcntl flags for ttyfd */
  649. #endif /* ultrix */
  650.     int fdflag = 0;            /* Flag for redirected stdio */
  651.     int ttfdflg = 0;            /* Open File descriptor was given */
  652.     int tvtflg = 0;            /* Flag that ttvt has been called */
  653.     long ttspeed = -1;            /* For saving speed */
  654.     int ttflow = -9;            /* For saving flow */
  655.     int ttld = -1;            /* Line discipline */
  656.  
  657. #ifdef sony_news
  658.     static int km_con = -1;        /* Kanji mode for console tty */
  659.     static int km_ext = -1;        /* Kanji mode for external device */
  660. #endif /* sony_news */
  661.  
  662. /*
  663.   Having this module rely on external globals is bad, but fixing this
  664.   requires overhaul of the ck*tio.c modules for all the different operating
  665.   systems supported by C-Kermit.  Left for a future release.
  666. */
  667. extern int ttnproto;            /* Defined in ckcnet.c */
  668. extern int ttnet;            /* Defined in ckcnet.c */
  669. extern int xfrcan, xfrchr, xfrnum;    /* Defined in ckcmai.c */
  670.  
  671. int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
  672.  
  673. /* Declarations of variables global within this module */
  674.  
  675. static time_t tcount;            /* Elapsed time counter */
  676. static SIGTYP (*saval)() = NULL;    /* For saving alarm() handler */
  677.  
  678. /*
  679.   BREAKNULS is defined for systems that simulate sending a BREAK signal
  680.   by sending a bunch of NUL characters at low speed.
  681. */
  682. #ifdef PROVX1
  683. #ifndef BREAKNULS
  684. #define BREAKNULS
  685. #endif /* BREAKNULS */
  686. #endif /* PROVX1 */
  687.  
  688. #ifdef V7
  689. #ifndef BREAKNULS
  690. #define BREAKNULS
  691. #endif /* BREAKNULS */
  692. #endif /* V7 */
  693.  
  694. #ifdef BREAKNULS
  695. static char                /* A string of nulls */
  696. *brnuls = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  697. #endif /* BREAKNULS */
  698.  
  699. static jmp_buf sjbuf;            /* Longjump buffers */
  700. #ifdef V7
  701. static jmp_buf jjbuf;
  702. #endif /* V7 */
  703.  
  704. /* static */                /* (Not static any more) */
  705. int ttyfd = -1;                /* TTY file descriptor */
  706.  
  707. int telnetfd = 0;            /* File descriptor is for telnet */
  708. int x25fd = 0;                /* File descriptor is for X.25 */
  709.  
  710. static int lkf = 0,                     /* Line lock flag */
  711.     cgmf = 0,                           /* Flag that console modes saved */
  712.     xlocal = 0,                         /* Flag for tty local or remote */
  713.     curcarr = 0;            /* Carrier mode: require/ignore. */
  714.  
  715. static int netconn = 0;            /* 1 if network connection active */
  716.  
  717. static char escchr;                     /* Escape or attn character */
  718.  
  719. #ifdef PS2AIX10
  720.     static struct timeval tv;        /* For getting time, from sys/time.h */
  721.     static struct timezone tz;
  722. #else
  723. #ifdef AIXRS
  724.     static struct timeval tv;        /* For getting time, from sys/time.h */
  725.     static struct timezone tz;
  726. #else
  727. #ifdef BSD44
  728.     static struct timeval tv;        /* For getting time, from sys/time.h */
  729.     static struct timezone tz;
  730. #else
  731. #ifdef BSD42
  732.     static struct timeval tv;        /* For getting time, from sys/time.h */
  733.     static struct timezone tz;
  734. #ifdef OSF
  735.     static struct timeb ftp;            /* And from sys/timeb.h */
  736. #endif /* OSF */
  737. #else
  738. #ifdef OXOS
  739.     static struct timeval tv;        /* For getting time, from sys/time.h */
  740.     static struct timezone tz;
  741. #endif /* OXOS */
  742. #endif /* BSD42 */
  743. #endif /* BSD44 */
  744. #endif /* AIXRS */
  745. #endif /* PS2AIX10 */
  746.  
  747. #ifdef QNX
  748.     static struct timeb ftp;        /* sys/timeb.h */
  749. #endif /* QNX */
  750.  
  751. #ifdef BSD29
  752.     static long xclock;                  /* For getting time from sys/time.h */
  753.     static struct timeb ftp;            /* And from sys/timeb.h */
  754. #endif /* BSD29 */
  755.  
  756. #ifdef BSD41
  757.     static long xclock;                  /* For getting time from sys/time.h */
  758.     static struct timeb ftp;            /* And from sys/timeb.h */
  759. #endif /* BSD41 */
  760.  
  761. #ifdef FT21
  762.     static long xclock;                  /* For getting time from sys/time.h */
  763.     static struct timeb ftp;            /* And from sys/timeb.h */
  764. #endif /* FT21 */
  765.  
  766. #ifdef TOWER1
  767.     static long xclock;            /* For getting time from sys/time.h */
  768.     static struct timeb ftp;        /* And from sys/timeb.h */
  769. #endif /* TOWER1 */
  770.  
  771. #ifdef COHERENT
  772.     static long xclock;            /* For getting time from sys/time.h */
  773.     static struct timeb ftp;        /* And from sys/timeb.h */
  774. #endif /* COHERENT */
  775.  
  776. #ifdef V7
  777.     static long xclock;
  778. #endif /* V7 */
  779.  
  780. /* sgtty/termio information... */
  781.  
  782. #ifdef BSD44ORPOSIX            /* POSIX or BSD44 */
  783.   static struct termios
  784.     ttold, ttraw, tttvt, ttcur,
  785.     ccold, ccraw, cccbrk;
  786. #else                    /* BSD, V7, etc */
  787. #ifdef ATTSV
  788.   static struct termio ttold = {0}; /* Init'd for word alignment, */
  789.   static struct termio ttraw = {0}; /* which is important for some */
  790.   static struct termio tttvt = {0}; /* systems, like Zilog... */
  791.   static struct termio ttcur = {0};
  792.   static struct termio ccold = {0};
  793.   static struct termio ccraw = {0};
  794.   static struct termio cccbrk = {0};
  795. #else
  796.   static struct sgttyb                  /* sgtty info... */
  797.     ttold, ttraw, tttvt, ttcur,     /* for communication line */
  798.     ccold, ccraw, cccbrk;        /* and for console */
  799. #ifdef TIOCGETC
  800. #ifdef MINIX
  801.   static struct sgttyb tchold, tchnoi;    /* Special chars */
  802. #else
  803.   static struct tchars tchold, tchnoi;
  804. #endif /* MINIX */
  805.   static int tcharf;
  806. #endif /* TIOCGETC */
  807. #ifdef TIOCGLTC
  808. #ifdef MINIX
  809.   static struct sgttyb ltchold, ltchnoi;
  810. #else
  811.   static struct ltchars ltchold, ltchnoi;
  812. #endif /* MINIX */
  813.   static int ltcharf;
  814. #endif /* TIOCGLTC */
  815.   int lmodef = 0;            /* Local modes */
  816.   int lmode = 0;
  817. #endif /* ATTSV */
  818. #endif /* BSD44ORPOSIX */
  819.  
  820. #ifdef PROVX1
  821.   static struct sgttyb ttbuf;
  822. #endif /* PROVX1 */
  823.  
  824. #ifdef ultrix
  825. /* do we really need this? */
  826.   static struct sgttyb vanilla;
  827. #endif /* ultrix */
  828.  
  829. #ifdef ATT7300
  830. static int attmodem = 0;                /* ATT7300 internal-modem status */
  831. struct updata dialer = {0};        /* Condition dialer for data call */
  832. #endif /* ATT7300 */
  833.  
  834. char flfnam[80];            /* uucp lock file path name */
  835. #ifdef RTAIX
  836. char lkflfn[80];            /* and possible link to it */
  837. #endif /* RTAIX */
  838. int haslock = 0;            /* =1 if this kermit locked uucp */
  839.  
  840. #ifndef OXOS
  841. #ifdef SVORPOSIX
  842. static int conesc = 0;                  /* set to 1 if esc char (^\) typed */
  843. #else
  844. #ifdef V7
  845. static int conesc = 0;
  846. #else
  847. #ifdef C70
  848. static int conesc = 0;
  849. #endif /* C70 */
  850. #endif /* V7 */
  851. #endif /* SVORPOSIX */
  852. #endif /* OXOS */
  853.  
  854. static char ttnmsv[DEVNAMLEN];        /* Copy of open path for tthang */
  855.  
  856. #ifdef aegis
  857. static status_$t st;                    /* error status return value */
  858. static short concrp = 0;                /* true if console is CRP pad */
  859. #define CONBUFSIZ 10
  860. static char conbuf[CONBUFSIZ];          /* console readahead buffer */
  861. static int  conbufn = 0;                /* # chars in readahead buffer */
  862. static char *conbufp;                   /* next char in readahead buffer */
  863. static uid_$t ttyuid;                   /* tty type uid */
  864. static uid_$t conuid;                   /* stdout type uid */
  865.  
  866. /* APOLLO Aegis main()
  867.  * establish acl usage and cleanup handling
  868.  *    this makes sure that CRP pads
  869.  *    get restored to a usable mode
  870.  */
  871. main(argc,argv) int argc; char **argv; {
  872.         status_$t status;
  873.         pfm_$cleanup_rec dirty;
  874.  
  875.         PID_T pid = getpid();
  876.  
  877.         /* acl usage according to invoking environment */
  878.         default_acl(USE_DEFENV);
  879.  
  880.         /* establish a cleanup continuation */
  881.         status = pfm_$cleanup(dirty);
  882.         if (status.all != pfm_$cleanup_set) {
  883.                 /* only handle faults for the original process */
  884.                 if (pid == getpid() && status.all > pgm_$max_severity) {
  885.             /* blew up in main process */
  886.             status_$t quo;
  887.             pfm_$cleanup_rec clean;
  888.  
  889.             /* restore the console in any case */
  890.             conres();
  891.  
  892.             /* attempt a clean exit */
  893.             debug(F101, "cleanup fault status", "", status.all);
  894.  
  895.             /* doexit(), then send status to continuation */
  896.             quo = pfm_$cleanup(clean);
  897.             if (quo.all == pfm_$cleanup_set)
  898.               doexit(pgm_$program_faulted,-1);
  899.             else if (quo.all > pgm_$max_severity)
  900.               pfm_$signal(quo); /* blew up in doexit() */
  901.                 }
  902.                 /* send to the original continuation */
  903.                 pfm_$signal(status);
  904.                 /*NOTREACHED*/
  905.         }
  906.         return(ckcmai(argc, argv));
  907. }
  908. #endif /* aegis */
  909.  
  910. /* ANSI-style prototypes for internal functions. */
  911. /* Functions used outside this module are prototyped in ckcker.h. */
  912.  
  913. #ifdef apollo
  914. _PROTOTYP( SIGTYP timerh, () );
  915. _PROTOTYP( SIGTYP cctrap, () );
  916. _PROTOTYP( SIGTYP esctrp, () );
  917. _PROTOTYP( SIGTYP sig_ign, () );
  918. #else
  919. _PROTOTYP( SIGTYP timerh, (int) );
  920. _PROTOTYP( SIGTYP cctrap, (int) );
  921. _PROTOTYP( SIGTYP esctrp, (int) );
  922. #endif /* apollo */
  923. _PROTOTYP( int do_open, (char *) );
  924. _PROTOTYP( int ttrpid, (char *) );
  925. _PROTOTYP( static int ttlock, (char *) );
  926. _PROTOTYP( static int ttunlck, (void) );
  927. _PROTOTYP( int mygetbuf, (void) );
  928. _PROTOTYP( int myfillbuf, (void) );
  929. _PROTOTYP( VOID conbgt, (int) );
  930. #ifdef ACUCNTRL
  931. _PROTOTYP( VOID acucntrl, (char *, char *) );
  932. #endif /* ACUCNTRL */
  933.  
  934. #ifdef BSD44ORPOSIX
  935. _PROTOTYP( int carrctl, (struct termios *, int) );
  936. #else
  937. #ifdef ATTSV
  938. _PROTOTYP( int carrctl, (struct termio *, int) );
  939. #else
  940. _PROTOTYP( int carrctl, (struct sgttyb *, int) );
  941. #endif /* ATTSV */
  942. #endif /* BSD44ORPOSIX */
  943.  
  944. #ifdef ATT7300
  945. _PROTOTYP( int attdial, (char *, long, char *) );
  946. _PROTOTYP( int offgetty, (char *) );
  947. _PROTOTYP( int ongetty, (char *) );
  948. #endif /* ATT7300 */
  949.  
  950. #ifdef CK_ANSIC
  951. static char *
  952. xxlast(char *s, char c)
  953. #else
  954. static char *
  955. xxlast(s,c) char *s; char c;
  956. #endif /* CK_ANSIC */
  957. /* xxlast */ {        /*  Last occurrence of character c in string s. */
  958.     int i;
  959.     for (i = (int)strlen(s); i > 0; i--)
  960.         if ( s[i-1] == c ) return( s + (i - 1) );
  961.     return(NULL);
  962. }
  963.  
  964. /* Timeout handler for communication line input functions */
  965.  
  966. SIGTYP
  967. timerh(foo) int foo; {
  968.     ttimoff();
  969.     longjmp(sjbuf,1);
  970. }
  971.  
  972. /* Control-C trap for communication line input functions */
  973.  
  974. int cc_int;                /* Flag */
  975. SIGTYP (* occt)();            /* For saving old SIGINT handler */
  976.  
  977. SIGTYP
  978. cctrap(foo) int foo; {            /* Needs arg for ANSI C */
  979.   cc_int = 1;                /* signal() prototype. */
  980.   return;
  981. }
  982.  
  983. /*  S Y S I N I T  --  System-dependent program initialization.  */
  984.  
  985. int
  986. sysinit() {
  987.     int x;
  988. #ifdef aegis
  989. #ifdef CK_CURSES
  990.     char trmbuf[1024];
  991. #endif /* CK_CURSES */
  992. #endif /* aegis */
  993.  
  994.     conbgt(0);                /* See if we're in the background */
  995.  
  996. #ifdef aegis
  997. #ifdef CK_CURSES
  998.     tgetent(trmbuf, getenv("TERM"));    /* Start vt100 emulator if needed */
  999. #endif /* CK_CURSES */
  1000. #endif /* aegis */
  1001.  
  1002. #ifndef __386BSD__
  1003. /*
  1004.   386BSD doesn't allow opening /dev/tty if Kermit is running setuid.
  1005. */
  1006.     congm();                /* Get console modes */
  1007. #endif /* __386BSD__ */
  1008.     signal(SIGALRM,SIG_IGN);        /* Ignore alarms */
  1009.  
  1010. #ifdef ultrix
  1011.     gtty(0,&vanilla);            /* Get sgtty info */
  1012.     iniflags = fcntl(0,F_GETFL,0);    /* Get flags */
  1013. #else
  1014. #ifdef AUX
  1015.     set42sig();                /* Don't ask! (hakanson@cs.orst.edu) */
  1016. #endif /* AUX */
  1017. #endif /* ultrix */
  1018.  
  1019. /* Initialize the setuid package. */
  1020. /* Change to the user's real user and group id. */
  1021. /* If this can't be done, don't run at all. */
  1022.  
  1023.     if (x = priv_ini()) {
  1024.     if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n");
  1025.     if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n");
  1026.     if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
  1027.     exit(1);
  1028.     }
  1029. #ifdef __386BSD__
  1030. /*
  1031.   386BSD...  OK, now we have changed into ourselves, so can open /dev/tty.
  1032. */
  1033.     congm();                /* Get console modes */
  1034. #endif /* __386BSD__ */
  1035.     return(0);
  1036. }
  1037.  
  1038. /*  S Y S C L E A N U P  --  System-dependent program cleanup.  */
  1039.  
  1040. int
  1041. syscleanup() {
  1042. #ifdef ultrix
  1043.     stty(0,&vanilla);                   /* Get sgtty info */
  1044.     fcntl(0,F_SETFL,iniflags);        /* Restore flags */
  1045. #endif /* ultrix */
  1046.     /* No need to call anything in the suid package here, right? */
  1047.     return(0);
  1048. }
  1049.  
  1050. /*  T T O P E N  --  Open a tty for exclusive access.  */
  1051.  
  1052. /*
  1053.   Call with:
  1054.     ttname: character string - device name or network host name.
  1055.     lcl:
  1056.   If called with lcl < 0, sets value of lcl as follows:
  1057.   0: the terminal named by ttname is the job's controlling terminal.
  1058.   1: the terminal named by ttname is not the job's controlling terminal.
  1059.   But watch out: if a line is already open, or if requested line can't
  1060.   be opened, then lcl remains (and is returned as) -1.
  1061.     modem:
  1062.   Less than zero: ttname is a network host name.
  1063.   Zero or greater: ttname is a terminal device name.    
  1064.   Zero means a local connection (don't use modem signals).
  1065.   Positive means use modem signals.  
  1066.    timo:
  1067.   0 = no timer.
  1068.   nonzero = number of seconds to wait for open() to return before timing out.
  1069.  
  1070.   Returns:
  1071.     0 on success
  1072.    -5 if device is in use
  1073.    -4 if access to device is denied
  1074.    -3 if access to lock directory denied
  1075.    -2 upon timeout waiting for device to open
  1076.    -1 on other error
  1077. */
  1078. static int ttotmo = 0;            /* Timeout flag */
  1079. /* Flag kept here to avoid being clobbered by longjmp.  */
  1080.  
  1081. int
  1082. ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
  1083.  
  1084. #ifdef BSD44
  1085. #define ctermid(x) strcpy(x,"")
  1086. #else
  1087. #ifdef SVORPOSIX
  1088. #ifndef CIE
  1089.     extern char *ctermid();        /* Wish they all had this! */
  1090. #else                    /* CIE Regulus */
  1091. #define ctermid(x) strcpy(x,"")
  1092. #endif /* CIE */
  1093. #endif /* SVORPOSIX */
  1094. #endif /* BSD44 */
  1095.  
  1096. #ifdef ultrix
  1097.     int temp = 0;
  1098. #endif /* ultrix */
  1099.  
  1100.     char *x;                /* Worker string pointer */
  1101.  
  1102. #ifndef MINIX
  1103.     extern char* ttyname();
  1104. #endif /* MINIX */
  1105.     char cname[DEVNAMLEN+4];
  1106.  
  1107. #ifndef pdp11
  1108. #define NAMEFD     /* Feature to allow name to be an open file descriptor */
  1109. #endif /* pdp11 */
  1110.  
  1111. #ifdef NAMEFD
  1112.     char *p;
  1113.  
  1114.     debug(F101,"ttopen telnetfd","",telnetfd);
  1115. #endif /* NAMEFD */
  1116.  
  1117.     debug(F111,"ttopen entry modem",ttname,modem);
  1118.     debug(F101," ttyfd","",ttyfd);
  1119.     debug(F101," lcl","",*lcl);
  1120.  
  1121. #ifdef MAXNAMLEN
  1122.     debug(F100,"ttopen MAXNAMLEN defined","",0);
  1123. #else
  1124.     debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
  1125. #endif
  1126.  
  1127. #ifdef BSD4
  1128.     debug(F100,"ttopen BSD4 defined","",0);
  1129. #else
  1130.     debug(F100,"ttopen BSD4 *NOT* defined","",0);
  1131. #endif
  1132.  
  1133. #ifdef BSD42
  1134.     debug(F100,"ttopen BSD42 defined","",0);
  1135. #else
  1136.     debug(F100,"ttopen BSD42 *NOT* defined","",0);
  1137. #endif /* BSD42 */
  1138.  
  1139. #ifdef MYREAD
  1140.     debug(F100,"ttopen MYREAD defined","",0);
  1141. #else
  1142.     debug(F100,"ttopen MYREAD *NOT* defined","",0);
  1143. #endif /* MYREAD */
  1144.  
  1145.     if (ttyfd > -1) {            /* if device already opened */
  1146.         if (strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
  1147.           ttclos(ttyfd);        /* no, close old ttname, open new */
  1148.         else                 /* else same, ignore this call, */
  1149.       return(0);            /* and return. */
  1150.     }
  1151.  
  1152. #ifdef    NETCONN
  1153.     if (modem < 0) {            /* modem < 0 = special code for net */
  1154.     int x;
  1155.     ttmdm = modem;
  1156.     modem = -modem;            /* Positive network type number */
  1157.     fdflag = 0;            /* Stdio not redirected. */
  1158.     netconn = 1;            /* And it's a network connection */
  1159.     debug(F111,"ttopen net",ttname,modem);
  1160. #ifdef NAMEFD
  1161.     for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
  1162.      if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
  1163.         ttyfd = atoi(ttname);    /* Is there a way to test it's open? */
  1164.         ttfdflg = 1;        /* We got an open file descriptor */
  1165.         debug(F111,"ttopen got open network fd",ttname,ttyfd);
  1166.         strncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
  1167.         x = 1;            /* Return code is "good". */
  1168.         if (telnetfd) {
  1169.         ttnet = NET_TCPB;
  1170.         ttnproto = NP_TELNET;
  1171. #ifdef SUNX25
  1172.         } else if (x25fd) {
  1173.         ttnet = NET_SX25;
  1174.         ttnproto = NP_NONE;
  1175. #endif /* SUNX25 */        
  1176.         }
  1177.     } else {            /* Host name or address given */
  1178. #endif /* NAMEFD */
  1179.         x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
  1180.         if (x > -1) {
  1181.         strncpy(ttnmsv,ttname,DEVNAMLEN);
  1182.         } else netconn = 0;
  1183. #ifdef NAMEFD
  1184.     }
  1185. #endif /* NAMEFD */
  1186.  
  1187. #ifdef sony_news            /* Sony NEWS */
  1188.     if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
  1189.         perror("ttopen error getting Kanji mode (network)");
  1190.         debug(F111,"ttopen error getting Kanji mode","network",0);
  1191.         km_ext = -1;        /* Make sure this stays undefined. */
  1192.     }
  1193. #endif /* sony_news */
  1194.  
  1195.     xlocal = *lcl = 1;        /* Network connections are local. */
  1196.     debug(F101,"ttopen net x","",x);
  1197.  
  1198.     if (x > -1 && !x25fd)
  1199.       x = tn_ini();            /* Initialize TELNET protocol */
  1200.     return(x);
  1201.     } else {                /* Terminal device */
  1202. #endif    /* NETCONN */
  1203.  
  1204. #ifdef NAMEFD
  1205. /*
  1206.   This code lets you give Kermit an open file descriptor for a serial
  1207.   communication device, rather than a device name.  Kermit assumes that the
  1208.   line is already open, locked, conditioned with the right parameters, etc.
  1209. */
  1210.     for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
  1211.     if (*p == '\0') {
  1212.         ttyfd = atoi(ttname);    /* Is there a way to test it's open? */
  1213.         debug(F111,"ttopen got open fd",ttname,ttyfd);
  1214.         strncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
  1215.         xlocal = *lcl = 1;        /* Assume it's local. */
  1216.         netconn = 0;        /* Assume it's not a network. */
  1217.         tvtflg = 0;            /* Might need to initialize modes. */
  1218.         ttmdm = modem;        /* Remember modem type. */
  1219.         fdflag = 0;            /* Stdio not redirected. */
  1220.         ttfdflg = 1;        /* Flag we were opened this way. */
  1221.  
  1222. #ifdef sony_news            /* Sony NEWS */
  1223.         /* Get device Kanji mode */
  1224.         if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
  1225.         perror("ttopen error getting Kanji mode");
  1226.         debug(F101,"ttopen error getting Kanji mode","",0);
  1227.         km_ext = -1;        /* Make sure this stays undefined. */
  1228.         }
  1229. #endif /* sony_news */
  1230.         return(0);            /* Return success */
  1231.     }
  1232. #endif /* NAMEFD */
  1233. #ifdef NETCONN
  1234.     }
  1235. #endif /* NETCONN */
  1236.  
  1237. /* Here we have to open a serial device of the given name. */
  1238.  
  1239.     occt = signal(SIGINT, cctrap);    /* Set Control-C trap, save old one */
  1240.  
  1241.     tvtflg = 0;            /* Flag for use by ttvt(). */
  1242.                 /* 0 = ttvt not called yet for this device */
  1243.  
  1244.     fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
  1245.     debug(F101,"ttopen fdflag","",fdflag);
  1246.  
  1247.     ttmdm = modem;                      /* Make this available to other fns */
  1248.     xlocal = *lcl;                      /* Make this available to other fns */
  1249.  
  1250. /* Code for handling bidirectional tty lines goes here. */
  1251. /* Use specified method for turning off logins and suppressing getty. */
  1252.  
  1253. #ifdef ACUCNTRL
  1254.     /* Should put call to priv_on() here, but that would be very risky! */
  1255.     acucntrl("disable",ttname);         /* acucntrl() program. */
  1256.     /* and priv_off() here... */
  1257. #else
  1258. #ifdef ATT7300
  1259.     if ((attmodem & DOGETY) == 0)       /* offgetty() program. */
  1260.       attmodem |= offgetty(ttname);    /* Remember response.  */
  1261. #endif /* ATT7300 */
  1262. #endif /* ACUCNTRL */
  1263.  
  1264. /*
  1265.  In the following section, we open the tty device for read/write.
  1266.  If a modem has been specified via "set modem" prior to "set line"
  1267.  then the O_NDELAY parameter is used in the open, provided this symbol
  1268.  is defined (e.g. in fcntl.h), so that the program does not hang waiting
  1269.  for carrier (which in most cases won't be present because a connection
  1270.  has not been dialed yet).  O_NDELAY is removed later on in ttopen().  It
  1271.  would make more sense to first determine if the line is local before
  1272.  doing this, but because ttyname() requires a file descriptor, we have
  1273.  to open it first.  See do_open().
  1274.  
  1275.  Now open the device using the desired treatment of carrier.
  1276.  If carrier is REQUIRED, then open could hang forever, so an optional
  1277.  timer is provided.  If carrier is not required, the timer should never
  1278.  go off, and should do no harm...
  1279. */
  1280.     ttotmo = 0;                /* Flag no timeout */
  1281.     if (timo > 0) {
  1282.     int xx;
  1283.     saval = signal(SIGALRM,timerh);    /* Timed, set up timer. */
  1284.     xx = alarm(timo);        /* Timed open() */
  1285.     debug(F101,"ttopen alarm","",xx);
  1286.     if (setjmp(sjbuf)) {
  1287.         ttotmo = 1;            /* Flag timeout. */
  1288.     } else ttyfd = do_open(ttname);
  1289.     ttimoff();
  1290.     debug(F111,"ttopen","modem",modem);
  1291.     debug(F101," ttyfd","",ttyfd);
  1292.     debug(F101," alarm return","",ttotmo);
  1293.     } else ttyfd = do_open(ttname);
  1294.     debug(F111,"ttopen ttyfd",ttname,ttyfd);
  1295.     if (ttyfd < 0) {            /* If couldn't open, fail. */
  1296. #ifdef ATT7300
  1297.     if (attmodem & DOGETY)        /* was getty(1m) running before us? */
  1298.       ongetty(ttnmsv);        /* yes, restart on tty line */
  1299.     attmodem &= ~DOGETY;        /* no phone in use, getty restored */
  1300. #else
  1301. #if ACUCNTRL
  1302.         /* Should put call to priv_on() here, but that would be risky! */
  1303.     acucntrl("enable",ttname);    /* acucntrl() program. */    
  1304.     /* and priv_off() here... */
  1305. #endif /* ACUNTRL */
  1306. #endif /* ATT7300 */
  1307.  
  1308.     signal(SIGINT,occt);        /* Put old Ctrl-C trap back. */
  1309.     if (errno == EACCES) {        /* Device is protected against user */
  1310.         perror(ttname);        /* Print message */
  1311.         debug(F111,"ttopen tty access denied",ttname,errno);
  1312.         return(-4);
  1313.     } else return(ttotmo ? -2 : -1);
  1314.     }
  1315.  
  1316.     /* Make sure it's a real tty. */
  1317.     if (!isatty(ttyfd)) {
  1318.     fprintf(stderr,"%s is not a tty!\n",ttname);
  1319.     debug(F110,"ttopen not a tty",ttname,0);
  1320.     close(ttyfd);
  1321.     ttyfd = -1;
  1322.     signal(SIGINT,occt);
  1323.     return(-1);
  1324.     }
  1325.  
  1326. #ifdef aegis
  1327.     /* Apollo C runtime claims that console pads are tty devices, which
  1328.      * is reasonable, but they aren't any good for packet transfer. */
  1329.     ios_$inq_type_uid((short)ttyfd, ttyuid, st);
  1330.     if (st.all != status_$ok) {
  1331.         fprintf(stderr, "problem getting tty object type: ");
  1332.         error_$print(st);
  1333.     } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
  1334.         close(ttyfd); ttyfd = -1;
  1335.         errno = ENOTTY; perror(ttname);
  1336.         signal(SIGINT,occt);
  1337.         return(-1);
  1338.     }
  1339. #endif /* aegis */
  1340.  
  1341.     strncpy(ttnmsv,ttname,DEVNAMLEN);   /*  Keep copy of name locally. */
  1342.  
  1343. /* Caller wants us to figure out if line is controlling tty */
  1344.  
  1345.     if (*lcl < 0) {
  1346.     int x0 = 0, x1 = 0;
  1347.         if (strcmp(ttname,CTTNAM) == 0) {   /* "/dev/tty" always remote */
  1348.             xlocal = 0;
  1349.         debug(F111," ttname=CTTNAM",ttname,xlocal);
  1350.  
  1351.     /* If any of 0, 1, or 2 not redirected, we can use ttyname() to get */
  1352.     /* the name of the controlling terminal... */
  1353.  
  1354. /*
  1355.   Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
  1356.   never closes it.  If it is called often enough, we run out of file
  1357.   descriptors and subsequent open()'s of other devices or files can fail.
  1358. */
  1359.  
  1360.         } else if ((x0 = isatty(0)) || (x1 = isatty(1)) || isatty(2)) {
  1361. #ifndef MINIX
  1362.         if (x0)
  1363.           x = ttyname(0);        /* and compare it with the */
  1364.         else if (x1)        /* tty device name. */
  1365.           x = ttyname(1);
  1366.         else x = ttyname(2);
  1367.             strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */
  1368.         debug(F110," cname",x,0);
  1369.             x = ttyname(ttyfd);         /* Gat real name of ttname. */
  1370.             xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;    /* Compare. */
  1371.         debug(F111," ttyname",x,xlocal);
  1372. #else
  1373.         xlocal = 1;            /* Can't do this test in MINIX */
  1374. #endif /* MINIX */
  1375.         } else {                        /* Else, if stdin redirected... */
  1376. #ifdef SVORPOSIX
  1377. /* System V provides nice ctermid() function to get name of controlling tty */
  1378.             ctermid(cname);             /* Get name of controlling terminal */
  1379.             debug(F110," ctermid",cname,0);
  1380.             x = ttyname(ttyfd);         /* Compare with name of comm line. */
  1381.             xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
  1382.             debug(F111," ttyname",x,xlocal);
  1383. #else
  1384. /* Just assume local */
  1385.             xlocal = 1;
  1386. #endif /* SVORPOSIX */
  1387.             debug(F101," redirected stdin","",xlocal);
  1388.         }
  1389.     }
  1390.  
  1391. #ifndef NOFDZERO
  1392. /* Note, the following code was added so that Unix "idle-line" snoopers */
  1393. /* would not think Kermit was idle when it was transferring files, and */
  1394. /* maybe log people out. */
  1395.     if (xlocal == 0) {            /* Remote mode */
  1396.     if (fdflag == 0) {        /* Standard i/o is not redirected */
  1397.         debug(F100,"ttopen setting ttyfd = 0","",0);
  1398.         close(ttyfd);        /* Use file descriptor 0 */
  1399.         ttyfd = 0;
  1400.     } else {            /* Standard i/o is redirected */
  1401.         debug(F101,"ttopen stdio redirected","",ttyfd);
  1402.     }
  1403.     }
  1404. #endif /* NOFDZERO */
  1405.  
  1406. /* Now check if line is locked -- if so fail, else lock for ourselves */
  1407. /* Note: After having done this, don't forget to delete the lock if you */
  1408. /* leave ttopen() with an error condition. */
  1409.  
  1410.     lkf = 0;                            /* Check lock */
  1411.     if (xlocal > 0) {
  1412.     int xx; int xpid;
  1413.         if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
  1414.             debug(F111,"ttopen ttlock fails",ttname,xx);
  1415.             close(ttyfd);        /* Close the device. */
  1416.         ttyfd = -1;            /* Erase its file descriptor. */
  1417.         signal(SIGINT,occt);    /* Put old SIGINT back. */
  1418.         if (xx == -2) {        /* If lockfile says tty is in use, */
  1419.         char *p = malloc(200);    /* print an ls -l listing */
  1420.         if (p) {        /* if we can get space... */
  1421.             sprintf(p,"/bin/ls -l %s",flfnam);
  1422.             zsyscmd(p);        /* Get listing. */
  1423.             free(p);        /* free the space */
  1424.             xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
  1425.             priv_off();        /* Turn privs back off. */
  1426.             if (xpid > -1) printf("pid = %d\n",xpid); /* show pid */
  1427.         }
  1428.         return(-5);        /* Code for device in use */
  1429.         } else return(-3);        /* Access denied */
  1430.         } else lkf = 1;
  1431.     }
  1432.  
  1433. /* Got the line, now set the desired value for local. */
  1434.  
  1435.     if (*lcl != 0) *lcl = xlocal;
  1436.  
  1437. /* Some special stuff for v7... */
  1438.  
  1439. #ifdef  V7
  1440. #ifndef MINIX
  1441.     if (kmem[TTY] < 0) {        /*  If open, then skip this.  */
  1442.     qaddr[TTY] = initrawq(ttyfd);   /* Init the queue. */
  1443.     if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
  1444.         fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
  1445.         perror("/dev/kmem");
  1446.         exit(1);
  1447.     }
  1448.     }
  1449. #endif /* !MINIX */
  1450. #endif /* V7 */
  1451.  
  1452. /* No failure returns after this point */
  1453.  
  1454. #ifdef ultrix
  1455.     ioctl(ttyfd, TIOCMODEM, &temp);
  1456. #ifdef TIOCSINUSE
  1457.     if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
  1458.     fprintf(stderr, "Can't set in-use flag on modem.\n");
  1459.     perror("TIOCSINUSE");
  1460.     }
  1461. #endif /* TIOCSINUSE */
  1462. #endif /* ultrix */
  1463.  
  1464. /* Get tty device settings */
  1465.  
  1466. #ifdef BSD44ORPOSIX            /* POSIX */
  1467.     tcgetattr(ttyfd,&ttold);
  1468.     debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
  1469.     tcgetattr(ttyfd,&ttraw);
  1470.     tcgetattr(ttyfd,&tttvt);
  1471. #else                    /* BSD, V7, and all others */
  1472. #ifdef ATTSV                /* AT&T UNIX */
  1473.     ioctl(ttyfd,TCGETA,&ttold);
  1474.     debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
  1475.     ioctl(ttyfd,TCGETA,&ttraw);
  1476.     ioctl(ttyfd,TCGETA,&tttvt);
  1477. #else
  1478.     gtty(ttyfd,&ttold);
  1479.     debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
  1480.  
  1481. #ifdef sony_news            /* Sony NEWS */
  1482.     if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
  1483.     perror("ttopen error getting Kanji mode");
  1484.     debug(F101,"ttopen error getting Kanji mode","",0);
  1485.     km_ext = -1;            /* Make sure this stays undefined. */
  1486.     }
  1487. #endif /* sony_news */
  1488.  
  1489. #ifdef TIOCGETC
  1490.     tcharf = 0;                /* In remote mode, also get */
  1491.     if (xlocal == 0) {            /* special characters */
  1492.     if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
  1493.         debug(F100,"ttopen TIOCGETC failed","",0);
  1494.     } else {
  1495.         tcharf = 1;            /* It worked. */
  1496.         ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
  1497.         debug(F100,"ttopen TIOCGETC ok","",0);
  1498.     }
  1499.     }    
  1500. #else
  1501.     debug(F100,"ttopen TIOCGETC not defined","",0);
  1502. #endif /* TIOCGETC */
  1503.  
  1504. #ifdef TIOCGLTC
  1505.     ltcharf = 0;            /* In remote mode, also get */
  1506.     if (xlocal == 0) {            /* local special characters */
  1507.     if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
  1508.         debug(F100,"ttopen TIOCGLTC failed","",0);
  1509.     } else {
  1510.         ltcharf = 1;        /* It worked. */
  1511.         ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
  1512.         debug(F100,"ttopen TIOCGLTC ok","",0);
  1513.     }
  1514.     }    
  1515. #else
  1516.     debug(F100,"ttopen TIOCGLTC not defined","",0);
  1517. #endif /* TIOCGLTC */
  1518.  
  1519. #ifdef TIOCLGET
  1520.     lmodef = 0;
  1521.     if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
  1522.     debug(F100,"ttopen TIOCLGET failed","",0);
  1523.     } else {
  1524.     lmodef = 1;
  1525.     debug(F100,"ttopen TIOCLGET ok","",0);
  1526.     }
  1527. #endif /* TIOCLGET */
  1528.  
  1529.     gtty(ttyfd,&ttraw);                 /* And a copy of it for packets*/
  1530.     gtty(ttyfd,&tttvt);                 /* And one for virtual tty service */
  1531.  
  1532. #endif /* ATTSV */
  1533. #endif /* BSD44ORPOSIX */
  1534.  
  1535.  
  1536. /* Section for changing line discipline.  It's restored in ttres(). */
  1537.  
  1538. #ifdef BSD41
  1539. /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
  1540.     { int k;
  1541.       ioctl(ttyfd, TIOCGETD, &ttld);    /* Get and save line discipline */
  1542.       debug(F101,"4.1bsd line discipline","",ttld);
  1543.       k = OTTYDISC;            /* Switch to "old" discipline */
  1544.       k = ioctl(ttyfd, TIOCSETD, &k);
  1545.       debug(F101,"4.1bsd tiocsetd","",k);
  1546.     }
  1547. #endif /* BSD41 */
  1548.  
  1549. #ifdef aegis
  1550.     /* This was previously done before the last two TCGETA or gtty above,
  1551.      * in both the ATTSV and not-ATTSV case.  If it is not okay to have only
  1552.      * one copy if it here instead, give us a shout!
  1553.      */
  1554.     sio_$control((short)ttyfd, sio_$raw_nl, false, st);
  1555.     if (xlocal) {       /* ignore breaks from local line */
  1556.         sio_$control((short)ttyfd, sio_$int_enable, false, st);
  1557.         sio_$control((short)ttyfd, sio_$quit_enable, false, st);
  1558.     }
  1559. #endif /* aegis */
  1560.  
  1561. #ifdef VXVE
  1562.     ttraw.c_line = 0;                   /* STTY line 0 for VX/VE */
  1563.     tttvt.c_line = 0;                   /* STTY line 0 for VX/VE */
  1564.     ioctl(ttyfd,TCSETA,&ttraw);
  1565. #endif /* vxve */
  1566.  
  1567. /* If O_NDELAY was used during open(), then remove it now. */
  1568.  
  1569. #ifdef O_NDELAY
  1570.     if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
  1571.  
  1572. #ifndef aegis
  1573.     if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
  1574.         perror("Can't unset O_NDELAY");
  1575. #endif /* aegis */
  1576.     /* Some systems, notably Xenix (don't know how common this is in
  1577.      * other systems), need special treatment to get rid of the O_NDELAY
  1578.      * behaviour on read() with respect to carrier presence (i.e. read()
  1579.      * returning 0 when carrier absent), even though the above fcntl()
  1580.      * is enough to make read() wait for input when carrier is present.
  1581.      * This magic, in turn, requires CLOCAL for working when the carrier
  1582.      * is absent. But if xlocal == 0, presumably you already have CLOCAL
  1583.      * or you have a carrier, otherwise you wouldn't be running this.
  1584.      */
  1585. #ifdef ATTSV
  1586. #ifdef BSD44
  1587.     tcsetattr(ttyfd, TCSADRAIN, &ttraw);
  1588. #else
  1589.     if (xlocal) {
  1590.         ttraw.c_cflag |= CLOCAL;
  1591.         ioctl(ttyfd, TCSETA, &ttraw);
  1592.     }
  1593. #endif /* BSD44 */
  1594. #endif /* ATTSV */
  1595. #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
  1596. /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
  1597.     close( priv_opn(ttname, O_RDWR) ); /* Magic to force change. */
  1598. #endif /* NOCOTFMC */
  1599.     }
  1600. #endif /* O_NDELAY */
  1601.  
  1602. /* Instruct the system how to treat the carrier, and set a few other tty
  1603.  * parameters.
  1604.  *
  1605.  * This also undoes the temporary setting of CLOCAL that may have been done
  1606.  * for the close(open()) above (except in Xenix).  Also throw in ~ECHO, to
  1607.  * prevent the other end of the line from sitting there talking to itself,
  1608.  * producing garbage when the user performs a connect.
  1609.  *
  1610.  * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
  1611.  * Now it thinks CLOCAL is always on. It seems the only real solution for
  1612.  * Xenix is to switch between the lower and upper case device names.
  1613.  *
  1614.  * This section may at some future time expand into setting a complete
  1615.  * collection of tty parameters, or call a function shared with ttpkt()/
  1616.  * ttvt() that does so.  On the other hand, the initial parameters are not
  1617.  * that important, since ttpkt() or ttvt() should always fix that before
  1618.  * any communication is done.  Well, we'll see...
  1619.  */
  1620.     if (xlocal) {
  1621.         curcarr = -2;
  1622.     carrctl(&ttraw, ttcarr == CAR_ON);
  1623.  
  1624. #ifdef SVORPOSIX
  1625.     ttraw.c_lflag &= ~ECHO;
  1626.     ttold.c_lflag &= ~ECHO;
  1627. #ifdef BSD44ORPOSIX
  1628.     tcsetattr(ttyfd, TCSADRAIN, &ttraw);
  1629. #else
  1630.     ioctl(ttyfd, TCSETA, &ttraw);
  1631. #endif /* BSD44ORPOSIX */
  1632.  
  1633. #else /* BSD, etc */
  1634.     ttraw.sg_flags &= ~ECHO;
  1635.     ttold.sg_flags &= ~ECHO;
  1636.     stty(ttyfd,&ttraw);
  1637. #endif /* SVORPOSIX */
  1638. /*    ttflui();  This fails for some reason  */
  1639.     }
  1640.     
  1641.     /* Get current speed */
  1642.  
  1643.     ttspeed = ttgspd();
  1644.     debug(F101,"ttopen ttspeed","",ttspeed);
  1645.  
  1646.     /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
  1647.  
  1648.     debug(F101,"ttopen, ttyfd","",ttyfd);
  1649.     debug(F101," lcl","",*lcl);
  1650.     debug(F111," lock file",flfnam,lkf);
  1651.     signal(SIGINT,occt);
  1652.     return(0);
  1653. }
  1654.  
  1655.  
  1656. /*  D O _ O P E N  --  Do the right kind of open() call for the tty. */
  1657.  
  1658. int
  1659. do_open(ttname) char *ttname; {
  1660.  
  1661. #ifndef    O_NDELAY            /* O_NDELAY not defined */
  1662.     return(priv_opn(ttname,2));
  1663. #else                    /* O_NDELAY defined */
  1664.  
  1665. #ifdef ATT7300
  1666. /*
  1667.  Open comms line without waiting for carrier so initial call does not hang
  1668.  because state of "modem" is likely unknown at the initial call  -jrd.
  1669.  If this is needed for the getty stuff to work, and the open would not work
  1670.  without O_NDELAY when getty is still on, then this special case is ok.
  1671.  Otherwise, get rid of it. -ske
  1672. */
  1673.     return(priv_opn(ttname, O_RDWR | O_NDELAY));
  1674.  
  1675. #else    /* !ATT7300 */
  1676.  
  1677.     /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
  1678.   
  1679.     return(priv_opn(ttname, O_RDWR | ((ttcarr != CAR_ON) ? O_NDELAY : 0) ));
  1680.  
  1681. #endif    /* !ATT7300 */
  1682. #endif    /* O_NDELAY */
  1683. }
  1684.  
  1685. /*  T T C L O S  --  Close the TTY, releasing any lock.  */
  1686.  
  1687. int
  1688. ttclos(foo) int foo; {            /* Arg req'd for signal() prototype */
  1689.     int x = 0;
  1690.  
  1691.     debug(F101,"ttclos ttyfd","",ttyfd);
  1692.     if (ttyfd < 0) return(0);           /* Wasn't open. */
  1693.  
  1694.     if (ttfdflg) return(0);        /* If we got ttyfd from another */
  1695.                     /* process, don't close it. */
  1696.     tvtflg = 0;
  1697. #ifdef    NETCONN
  1698.     if (netconn) {            /* Network connection. */
  1699.     debug(F100,"ttclos closing net","",0);
  1700.     netclos();            /* Close it. */
  1701.     netconn = 0;
  1702.     return(0);
  1703.     }
  1704. #endif    /* NETCONN */
  1705. #ifdef FT21
  1706.     if (xlocal) ioctl(ttyfd,TIOCHPCL, NULL);
  1707. #endif /* FT21 */
  1708. #ifdef ultrix
  1709.     /*** if (xlocal) ioctl(ttyfd, TIOCNCAR, NULL); ***/
  1710.     if (xlocal) ioctl(ttyfd, TIOCNMODEM, &x);
  1711. #endif /* ultrix */
  1712.     if (xlocal) {
  1713.     debug(F100,"ttclos about to call ttunlck","",0);
  1714.         if (ttunlck())                  /* Release uucp-style lock */
  1715.       fprintf(stderr,"Warning, problem releasing lock\r\n");
  1716.     debug(F100,"ttclos about to call ttres","",0);
  1717.     }
  1718.     if (ttyfd > 0) {
  1719.     int xx;
  1720.     saval = signal(SIGALRM,timerh);    /* Enable timer interrupt. */
  1721.     xx = alarm(5);            /* Allow 5 seconds for this. */
  1722.     debug(F101,"ttclos alarm","",xx);
  1723.     if (setjmp(sjbuf)) {        /* Timer went off? */
  1724.         x = -1;
  1725.     } else {            /* What we're really trying to do */
  1726.         if (xlocal) {
  1727.         tthang();        /* Hang up first, then... */
  1728.         ttres();        /* reset device modes. */
  1729.         }
  1730.         debug(F101,"ttclos about to call close","",ttyfd);
  1731.         close(ttyfd);        /* Close the device. */
  1732.         x = 1;
  1733.     }
  1734.     ttimoff();            /* Turn off timer. */
  1735.     if (x < 0) {
  1736.         fprintf(stderr,"?Timed out closing device: %s\n",ttnmsv);
  1737.         debug(F100,"ttclos timed out","",0);
  1738.     }
  1739.     }
  1740.     ttyfd = -1;                         /* Invalidate the file descriptor. */
  1741. #ifdef sony_news
  1742.     km_ext = -1;            /* Invalidate device's Kanji-mode */
  1743. #endif /* sony_news */
  1744.  
  1745. /* For bidirectional lines, restore getty if it was there before. */
  1746.  
  1747. #ifdef ACUCNTRL                /* 4.3BSD acucntrl() method. */
  1748.     acucntrl("enable",ttnmsv);        /* Enable getty on the device. */
  1749. #else
  1750. #ifdef ATT7300                /* ATT UNIX PC (3B1, 7300) method. */
  1751.     if (attmodem & DOGETY)              /* Was getty(1m) running before us? */
  1752.       ongetty(ttnmsv);            /* Yes, restart getty on tty line */
  1753.     attmodem &= ~DOGETY;                /* No phone in use, getty restored */
  1754. #endif /* ATT7300 */
  1755. #endif /* System-dependent getty-restoring methods */
  1756.  
  1757.     debug(F100,"ttclos done","",0);
  1758.     return(0);
  1759. }
  1760.  
  1761. /*  T T H A N G  --  Hangup phone line or network connection.  */
  1762. /*
  1763.   Returns:
  1764.   0 if it does nothing.
  1765.   1 if it believes that it hung up successfully.
  1766.  -1 if it believes that the hangup attempt failed.
  1767. */
  1768.  
  1769. #define HUPTIME 500            /* Milliseconds for hangup */
  1770.  
  1771. int
  1772. tthang() {
  1773.     int x = 0;                /* Sometimes used as return code. */
  1774. #ifndef POSIX
  1775.     int z;                /* worker */
  1776. #endif /* POSIX */
  1777.  
  1778. #ifdef SVORPOSIX            /* AT&T, POSIX, HPUX declarations. */
  1779.     int spdsav;                /* for saving speed */
  1780.     int spdsavi;
  1781. #ifdef HPUX
  1782.     mflag dtr_down = 00000000000,
  1783.     modem_rtn;
  1784.     mflag modem_sav;
  1785.     char modem_state[64];
  1786. #endif /* HPUX */
  1787.     int flags;                /* fcntl flags */
  1788.     unsigned short ttc_save;
  1789. #endif /* SVORPOSIX */
  1790.  
  1791.     if (ttyfd < 0) return(0);           /* Don't do this if not open  */
  1792.     if (xlocal < 1) return(0);        /* Don't do this if not local */
  1793.  
  1794. #ifdef NETCONN
  1795.     if (netconn)            /* Network connection. */
  1796.       return((netclos() < 0) ? -1 : 1);    /* Just close it. */
  1797. #endif /* NETCONN */
  1798.  
  1799. /* From here down, we handle real tty devices. */
  1800.  
  1801. #ifdef BSD44ORPOSIX
  1802. /* Should add some error checking here... */
  1803.     debug(F100,"tthang POSIX style","",0);
  1804.     spdsav = cfgetospeed(&ttcur);    /* Get current speed */
  1805.     spdsavi = cfgetispeed(&ttcur);    /* Get current speed */
  1806.     cfsetospeed(&ttcur,B0);        /* Replace by 0 */
  1807.     cfsetispeed(&ttcur,B0);
  1808.     if (tcsetattr(ttyfd,TCSADRAIN,&ttcur) == -1)
  1809.       debug(F100,"tthang tcsetattr fails","",errno);
  1810.     msleep(HUPTIME);            /* Sleep */
  1811.     cfsetospeed(&ttcur,spdsav);        /* Restore previous speed */
  1812.     cfsetispeed(&ttcur,spdsavi);
  1813.     tcsetattr(ttyfd,TCSADRAIN,&ttcur);
  1814.     return(1);
  1815.  
  1816. #else /* BSD44ORPOSIX */
  1817.  
  1818. #ifdef aegis                /* Apollo Aegis */
  1819.     sio_$control((short)ttyfd, sio_$dtr, false, st);    /* DTR down */
  1820.     msleep(HUPTIME);                    /* pause */
  1821.     sio_$control((short)ttyfd, sio_$dtr, true,  st);    /* DTR up */
  1822.     return(1);
  1823. #endif /* aegis */
  1824.  
  1825. #ifdef ANYBSD                /* Any BSD version. */
  1826.     debug(F100,"tthang BSD style","",0);
  1827.     if (ioctl(ttyfd,TIOCCDTR,0) < 0) {    /* Clear DTR. */
  1828.     debug(F101,"tthang TIOCCDTR fails","",errno);
  1829.     return(-1);
  1830.     }
  1831.     msleep(HUPTIME);            /* For about 1/2 sec */
  1832.     errno = 0;
  1833.     x = ioctl(ttyfd,TIOCSDTR,0);    /* Restore DTR */
  1834.     if (x < 0) {
  1835.     /*
  1836.       For some reason, this tends to fail with "no such device or address"
  1837.       but the operation still works, probably because of the close/open
  1838.       later on.  So let's not scare the user unnecessarily here.
  1839.     */
  1840.     debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
  1841.     x = 1;                /* Pretend we succeeded */
  1842.     } else if (x == 0) x = 1;        /* Success */
  1843. #ifdef COMMENT
  1844. #ifdef FT21
  1845.     ioctl(ttyfd, TIOCSAVEMODES, 0);
  1846.     ioctl(ttyfd, TIOCHPCL, 0);
  1847.     close(ttyfd);            /* Yes, must do this twice */
  1848.     if ((ttyfd = open(ttnmsv,2)) < 0)    /* on Fortune computers... */
  1849.       return(-1);            /* (but why?) */
  1850.     else x = 1;
  1851. #endif /* FT21 */
  1852. #endif /* COMMENT */
  1853.     close(do_open(ttnmsv));        /* Clear i/o error condition */
  1854.     errno = 0;
  1855. #ifdef COMMENT
  1856. /* This is definitely dangerous.  Why was it here? */
  1857.     z = ttvt(ttspeed,ttflow);        /* Restore modes. */
  1858.     debug(F101,"tthang ttvt returns","",z);
  1859.     return(z < 0 ? -1 : 1);
  1860. #else
  1861.     return(x);
  1862. #endif /* COMMENT */
  1863. #endif /* ANYBSD */
  1864.  
  1865. #ifdef ATTSV                
  1866. /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
  1867.  
  1868. #ifdef HPUX 
  1869. /* Hewlett Packard allows explicit manipulation of modem signals. */
  1870.  
  1871. #ifdef COMMENT
  1872. /* Old way... */
  1873.     debug(F100,"tthang HP-UX style","",0);
  1874.     if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0)        /* lower DTR */
  1875.       return(-1);                           /* oops, can't. */
  1876.     msleep(HUPTIME);                       /* Pause half a second. */
  1877.     x = 1;                           /* Set return code */
  1878.     if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) {     /* Get line status. */
  1879.     if ((modem_rtn & MDCD) != 0)             /* Check if CD is low. */
  1880.       x = -1;                                  /* CD didn't drop, fail. */
  1881.     } else x = -1;
  1882.  
  1883.     /* Even if above calls fail, RTS & DTR should be turned back on. */
  1884.     modem_rtn = MRTS | MDTR;
  1885.     if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
  1886.     return(x);
  1887. #else
  1888. /* New way, from Hellmuth Michaelis */
  1889.     debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
  1890.     if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
  1891.     debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
  1892.     return(-1);
  1893.     }
  1894.     sprintf(modem_state,"%#lx",modem_rtn);
  1895.     debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);    
  1896.     modem_sav = modem_rtn;        /* save line status */
  1897.     modem_rtn &= ~MDTR;            /* DTR bit down */
  1898.     sprintf(modem_state,"%#lx",modem_rtn);
  1899.     debug(F110,"tthang HP-UX: modem lines lowered DTR = ",modem_state,0); 
  1900.     if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
  1901.     debug(F100,"tthang HP-UX: can't lower DTR!","",0);
  1902.     return(-1);            /* oops, can't. */
  1903.     }
  1904.     msleep(HUPTIME);            /* Pause half a second. */
  1905.     x = 1;                /* Set return code */
  1906.     if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
  1907.     sprintf(modem_state,"%#lx",modem_rtn);
  1908.     debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);    
  1909.     if ((modem_rtn & MDCD) != 0) {    /* Check if CD is low. */
  1910.         debug(F100,"tthang HP-UX: DCD didn't get down!","",0);
  1911.         x = -1;            /* CD didn't drop, fail. */
  1912.     } else {
  1913.         debug(F100,"tthang HP-UX: DCD down!","",0);
  1914.     }
  1915.     } else {
  1916.     x = -1;
  1917.     debug(F100,"tthang HP-UX: can't get DCD status !","",0);
  1918.     }
  1919.  
  1920.     /* Even if above calls fail, RTS & DTR should be turned back on. */
  1921.  
  1922.     modem_sav |= (MRTS | MDTR);
  1923.     if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
  1924.     x = -1;
  1925.     debug(F100,"tthang HP-UX: can't set saved state |=(RTS | DTR)","",0);
  1926.     } else {
  1927.     sprintf(modem_state,"%#lx",modem_sav);
  1928.     debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);    
  1929.     }        
  1930.     return(x);
  1931. #endif /* COMMENT */
  1932.  
  1933. #else /* AT&T but not HP-UX */
  1934.  
  1935. /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
  1936. /* It is not known how many, if any, systems actually implement them, */
  1937. /* so we include them here in ifdef's. */
  1938.  
  1939. #ifndef _IBMR2
  1940. /*
  1941.   No modem-signal twiddling for IBM RT PC or RS/6000.
  1942.   In AIX 3.1 and earlier, the ioctl() call is broken.
  1943.   This code could be activated for AIX 3.1 with PTF 2006 or later
  1944.   (e.g. AIX 3.2), but close/open does the job too, so why bother.
  1945. */
  1946. #ifdef TIOCMBIS                /* Bit Set */
  1947. #ifdef TIOCMBIC                /* Bit Clear */
  1948. #ifdef TIOCM_DTR            /* DTR */
  1949.  
  1950. /* Clear DTR, sleep 300 msec, turn it back on. */
  1951. /* If any of the ioctl's return failure, go on to the next section. */
  1952.  
  1953.     z = TIOCM_DTR;            /* Code for DTR. */
  1954. #ifdef TIOCM_RTS            /* Lower RTS too if symbol is known. */
  1955.     z |= TIOCM_RTS;            
  1956. #endif /* TIOCM_RTS */
  1957.  
  1958.     debug(F101,"tthang TIOCM signal mask","",z);
  1959.     if (ioctl(ttyfd,TIOCMBIC,&z) > -1) {   /* Try to lower DTR. */
  1960.     debug(F100,"tthang TIOCMBIC ok","",0);
  1961.     msleep(HUPTIME);           /* Pause half a second. */
  1962.     if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
  1963.         debug(F100,"tthang TIOCMBIS ok","",0);
  1964. #ifndef CLSOPN
  1965.         return(1);            /* Success, done. */
  1966. #endif /* CLSOPN */
  1967.     } else {            /* Couldn't raise, continue. */
  1968.         debug(F101,"tthang TIOCMBIS errno","",errno);
  1969.     }
  1970.     } else {                /* Couldn't lower, continue. */
  1971.      debug(F101,"tthang TIOCMBIC errno","",errno);
  1972.     }
  1973. #endif /* TIOCM_DTR */
  1974. #endif /* TIOCMBIC */
  1975. #endif /* TIOCMBIS */
  1976. #endif /* _IBMR2 */
  1977. /*
  1978.   General AT&T UNIX case, not HPUX.  The following code is highly suspect.  No
  1979.   two AT&T-based systems seem to do this the same way.  The object is simply
  1980.   to turn off DTR and then turn it back on.  SVID says the universal method
  1981.   for turning off DTR is to set the speed to zero, and this does seem to do
  1982.   the trick in all cases.  But neither SVID nor any known man pages say how to
  1983.   turn DTR back on again.  Some variants, like most Xenix implementations,
  1984.   raise DTR again when the speed is restored to a nonzero value.  Others
  1985.   require the device to be closed and opened again, but this is risky because
  1986.   getty could seize the device during the instant it is closed.
  1987. */
  1988.  
  1989. /* Return code for ioctl failures... */
  1990. #ifdef ATT6300
  1991.     x = 1;                /* ATT6300 doesn't want to fail... */
  1992. #else
  1993.     x = -1;
  1994. #endif /* ATT6300 */
  1995.  
  1996.     debug(F100,"tthang get settings","",0);
  1997.     if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
  1998.       return(x);            /* Fail if this doesn't work. */
  1999.     if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
  2000.       return(x);
  2001.     ttc_save = ttcur.c_cflag;        /* Remember current speed. */
  2002.     spdsav = ttc_save & CBAUD;
  2003.     debug(F101,"tthang speed","",spdsav);
  2004.  
  2005. #ifdef O_NDELAY
  2006.     debug(F100,"tthang turning O_NDELAY on","",0);
  2007.     fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
  2008. #endif /* O_NDELAY */
  2009.  
  2010. #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
  2011.     ttcur.c_cflag &= ~CBAUD;        /* Change the speed to zero.  */
  2012. #else
  2013. #ifdef RTAIX
  2014.     ttcur.c_cflag &= ~CBAUD;        /* Change the speed to zero.  */
  2015. #else          /* This way really works but may be dangerous */
  2016. #ifdef u3b2
  2017.     ttcur.c_cflag = ~(CBAUD|CLOCAL);    /* Special for AT&T 3B2s */
  2018.                     /* (CLOCAL must be OFF) */
  2019. #else
  2020. #ifdef SCO3R2                /* SCO UNIX 3.2 */
  2021. /*
  2022.   This is complete nonsense, but an SCO user claimed this change made
  2023.   hanging up work.  Comments from other SCO UNIX 3.2 users would be 
  2024.   appreciated.
  2025. */
  2026.     ttcur.c_cflag = CBAUD|B0;
  2027. #else
  2028. #ifdef AIXRS                /* AIX on RS/6000 */
  2029. /*
  2030.   Can't set speed to zero on AIX 3.1 or 3.1 on RS/6000 64-port adapter,
  2031.   even though you can do it on the built-in port and the 8- and 16-port
  2032.   adapters.  (Untested on 128-port adapter.)
  2033. */
  2034.     ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
  2035. #else                    /* None of the above */
  2036. /*
  2037.   Set everything, including the speed, to zero, except for the CLOCAL
  2038.   and HUPCL bits.
  2039. */
  2040.     ttcur.c_cflag = CLOCAL|HUPCL;
  2041. #endif /* AIXRS */
  2042. #endif /* SCO3R2 */
  2043. #endif /* u3b2 */
  2044. #endif /* RTAIX */
  2045. #endif /* ATT7300 */
  2046.  
  2047. #ifdef COMMENT
  2048.     /* and if none of those work, try one of these... */
  2049.     ttcur.c_cflag = 0;
  2050.     ttcur.c_cflag = CLOCAL;
  2051.     ttcur.c_cflag &= ~(CBAUD|HUPCL);
  2052.     ttcur.c_cflag &= ~(CBAUD|CREAD);
  2053.     ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
  2054.     /* or other combinations */
  2055. #endif /* COMMENT */
  2056.  
  2057. #ifdef TCXONC
  2058.     debug(F100,"tthang TCXONC","",0);
  2059.     ioctl(ttyfd, TCXONC, 1);
  2060. #endif /* TCXONC */
  2061.  
  2062. #ifdef TIOCSTART
  2063.     debug(F100,"tthang TIOCSTART","",0);
  2064.     ioctl(ttyfd, TIOCSTART, 0);
  2065. #endif /* TIOCSTART */
  2066.  
  2067.     if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
  2068.     fcntl(ttyfd, F_SETFL, flags);    /* Restore flags */
  2069.     return(-1);            /* before returning. */
  2070.     }
  2071.     msleep(300);            /* Give modem time to notice. */
  2072.  
  2073. /* Now, even though it doesn't say this in SVID or any man page, we have */
  2074. /* to close and reopen the device.  This is not necessary for all systems, */
  2075. /* but it's impossible to predict which ones need it and which ones don't. */
  2076.  
  2077. #ifdef ATT7300
  2078. /*
  2079.   Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
  2080.   related ioctl's for their internal modems.  attmodem has getty status and 
  2081.   modem-in-use bit.  Reportedly the ATT7300/3B1 PIOCDISC call is necessary, 
  2082.   but also ruins the file descriptor, and no other phone(7) ioctl call can fix 
  2083.   it.  Whateverit does, it seems to escape detection with PIOCGETA and TCGETA.
  2084.   The only way to undo the damage is to close the fd and then reopen it.
  2085. */
  2086.     if (attmodem & ISMODEM) {
  2087.     debug(F100,"tthang attmodem close/open","",0);
  2088.     ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
  2089.     ioctl(ttyfd,PIOCDISC,&dialer);    /* Disconnect phone. */
  2090.     close(ttyfd);            /* Close and reopen the fd. */
  2091.     ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
  2092.     attmodem &= ~ISMODEM;        /* Phone no longer in use. */
  2093.     }
  2094. #else /* !ATT7300 */
  2095. /* It seems we have to close and open the device for other AT&T systems */
  2096. /* too, and this is the place to do it.  The following code does the */
  2097. /* famous close(open(...)) magic by default.  If that doesn't work for you, */
  2098. /* then try uncommenting the following statement or putting -DCLSOPN in */
  2099. /* the makefile CFLAGS. */
  2100.  
  2101. /* #define CLSOPN */
  2102.  
  2103. #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
  2104.  
  2105. #ifdef O_NDELAY
  2106. #define OPENFLGS O_RDWR | O_NDELAY
  2107. #else
  2108. #define OPENFLGS O_RDWR
  2109. #endif
  2110.  
  2111. #ifndef CLSOPN
  2112. /* This method is used by default, i.e. unless CLSOPN is defined. */
  2113. /* It is thought to be safer because there is no window where getty */
  2114. /* can seize control of the device.  The drawback is that it might not work. */
  2115.  
  2116.     debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
  2117.     close(priv_opn(ttnmsv, OPENFLGS));
  2118.  
  2119. #else
  2120. /* This method is used if you #define CLSOPN.  It is more likely to work */
  2121. /* than the previous method, but it's also more dangerous. */
  2122.  
  2123.     debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
  2124.     close(ttyfd);
  2125.     msleep(10);
  2126.     ttyfd = priv_opn(ttnmsv, OPENFLGS);    /* Open it again */
  2127. #endif /* CLSOPN */
  2128. #undef OPENFLGS
  2129.  
  2130. #endif /* SCO32 */
  2131. #endif /* ATT7300 */
  2132.  
  2133. /* Now put all flags & modes back the way we found them. */
  2134. /* (Does the order of ioctl & fcntl matter ? ) */
  2135.  
  2136.     debug(F100,"tthang restore settings","",0);
  2137.     ttcur.c_cflag = ttc_save;        /* Get old speed back. */
  2138.     if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
  2139.       return(-1); 
  2140. #ifdef O_NDELAY
  2141. /*
  2142.   This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
  2143.   After closing a modem line, the modem will probably not be asserting
  2144.   carrier any more, so we should not require carrier any more.  If this
  2145.   causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
  2146.   than O_NDELAY.
  2147. */
  2148.     flags &= ~O_NDELAY;            /* Don't require carrier on reopen */
  2149. #endif /* O_NDELAY */
  2150.     if (fcntl(ttyfd,F_SETFL,flags) < 0)    /* fcntl parameters */
  2151.       return(-1);
  2152.  
  2153.     return(1);
  2154. #endif /* not HPUX */
  2155. #endif /* ATTSV */
  2156. #endif /* BSD44ORPOSIX */
  2157. }
  2158.  
  2159. /*
  2160.   Major change in 5A(174).  We used to use LPASS8, if it was defined, to
  2161.   allow 8-bit data and Xon/Xoff flow control at the same time.  But this
  2162.   LPASS8 business seems to have been causing trouble for everybody but me!
  2163.   For example, Annex terminal servers, commonly used with Encore computers,
  2164.   do not support LPASS8 even though the Encore itself does.  Ditto for many
  2165.   other terminal servers, TELNET connections, rlogin connections, etc etc.
  2166.   Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
  2167.   serial lines, even though LPASS8 is a feature of 4.3BSD.  So let's turn it
  2168.   off for everybody.  That means we goes back to using raw mode, with no
  2169.   flow control.  Phooey.
  2170.  
  2171.   NOTE: This must be done before the first reference to LPASS8 in this file,
  2172.   and after the last #include statment.
  2173. */
  2174. #ifdef LPASS8
  2175. #undef LPASS8
  2176. #endif /* LPASS8 */
  2177.  
  2178. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  2179.  
  2180. /* ske@pkmab.se: There are two choices for what this function should do.
  2181.  * (1) Restore the tty to current "normal" mode, with carrier treatment
  2182.  * according to ttcarr, to be used after every kermit command. (2) Restore
  2183.  * the tty to the state it was in before kermit opened it. These choices
  2184.  * conflict, since ttold can't hold both choices of tty parameters.  ttres()
  2185.  * is currently being called as in choice (1), but ttold basically holds
  2186.  * the initial parameters, as in (2), and the description at the beginning
  2187.  * of this file says (2).
  2188.  *
  2189.  * I don't think restoring tty parameters after all kermit commands makes
  2190.  * much of a difference.  Restoring them upon exit from kermit may be of
  2191.  * some use in some cases (when the line is not restored automatically on
  2192.  * close, by the operating system).
  2193.  *
  2194.  * I can't choose which one it should be, so I haven't changed it. It
  2195.  * probably works as it is, too. It would probably even work even with
  2196.  * ttres() entirely deleted...
  2197.  *
  2198.  * (from fdc: Actually, this function operates in remote mode too, so
  2199.  * it restores the console (command) terminal to whatever mode it was
  2200.  * in before packet operations began, so that commands work right again.)
  2201.  */
  2202. int
  2203. ttres() {                               /* Restore the tty to normal. */
  2204.     int x;
  2205.  
  2206.     if (ttyfd < 0) return(-1);          /* Not open. */
  2207.  
  2208.     if (ttfdflg) return(0);        /* Don't mess with terminal modes if */
  2209.                     /* we got ttyfd from another process */
  2210. #ifdef    NETCONN
  2211.     if (netconn) return (0);        /* Network connection, do nothing */
  2212. #endif    /* NETCONN */
  2213.  
  2214. /* Real terminal device, so restore its original modes */
  2215.  
  2216. #ifdef BSD44ORPOSIX            /* For POSIX like this */
  2217.     x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
  2218. #else                    /* For all others... */
  2219. #ifdef ATTSV                            /* For AT&T versions... */
  2220.     x = ioctl(ttyfd,TCSETAW,&ttold);    /* Restore tty modes this way. */
  2221. #else
  2222.     msleep(HUPTIME);            /* This replaces sleep(1)... */
  2223.                     /* Put back sleep(1) if tty is */
  2224.                     /* messed up after close. */
  2225.  
  2226. /* Here we restore the modes for BSD */
  2227.  
  2228. #ifdef LPASS8                /* Undo "pass8" if it were done */
  2229.     if (lmodef) {
  2230.     if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
  2231.       debug(F100,"ttres TIOCLSET failed","",0);
  2232.     else
  2233.       debug(F100,"ttres TIOCLSET ok","",0);
  2234.     }
  2235. #endif /* LPASS8 */
  2236.  
  2237. #ifdef CK_DTRCTS           /* Undo hardware flow if it were done */
  2238.     if (lmodef) {
  2239.      if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
  2240.        debug(F100,"ttres TIOCLSET failed","",0);
  2241.      else
  2242.        debug(F100,"ttres TIOCLSET ok","",0);
  2243.     }
  2244. #endif /* CK_DTRCTS */
  2245.  
  2246. #ifdef TIOCGETC                /* Put back special characters */
  2247.     if (tcharf && (xlocal == 0)) {
  2248.     if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
  2249.       debug(F100,"ttres TIOCSETC failed","",0);
  2250.     else
  2251.       debug(F100,"ttres TIOCSETC ok","",0);
  2252.     }
  2253. #endif /* TIOCGETC */
  2254.  
  2255. #ifdef TIOCGLTC                /* Put back local special characters */
  2256.     if (ltcharf && (xlocal == 0)) {
  2257.     if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
  2258.       debug(F100,"ttres TIOCSLTC failed","",0);
  2259.     else
  2260.       debug(F100,"ttres TIOCSLTC ok","",0);
  2261.     }
  2262. #endif /* TIOCGLTC */
  2263.  
  2264.     x = stty(ttyfd,&ttold);             /* restore tty modes the old way. */
  2265.  
  2266. #endif /* ATTSV */
  2267. #endif /* BSD44ORPOSIX */
  2268.  
  2269.     debug(F101,"ttres tty modes restore","",x);
  2270.     if (x < 0) debug(F101,"ttres errno","",errno);
  2271.  
  2272. #ifdef BSD41
  2273.     if (ttld > -1) {            /* Put back line discipline */
  2274.     x = ioctl(ttyfd, TIOCSETD, &ttld);
  2275.     debug(F101,"ttres line discipline restore","",x);
  2276.     if (x < 0) debug(F101,"...ioctl errno","",errno);
  2277.     ttld = -1;
  2278.     }
  2279. #endif /* BSD41 */
  2280.  
  2281. #ifdef sony_news
  2282.     x = xlocal ? km_ext : km_con;    /* Restore Kanji mode. */
  2283.     if (x != -1) {            /* Make sure we know original modes. */
  2284.     if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
  2285.         perror("ttres can't set Kanji mode");
  2286.         debug(F101,"ttres error setting Kanji mode","",x);
  2287.         return(-1);
  2288.     }
  2289.     }
  2290.     debug(F100,"ttres set Kanji mode ok","",0);
  2291. #endif /* sony_news */
  2292.  
  2293.     tvtflg = 0;                /* Invalidate terminal mode settings */
  2294.     return(x);
  2295. }
  2296.  
  2297. /*  T T R P I D  --  Read pid from lockfile "name" (used by ttlock) */
  2298.  
  2299. static int
  2300. ttrpid(name) char *name; {
  2301.     int x, fd, pid;
  2302.  
  2303.     fd = open(name,O_RDONLY);        /* Try to open lockfile. */
  2304.     if (fd > 0) {
  2305.  
  2306. #ifdef PIDSTRING
  2307.     char buf[12];
  2308.     x = read(fd, buf, 11);        /* For HDP UUCP, read pid string */
  2309.     if (x < 0) return(-1);
  2310.     buf[11] = '\0';
  2311.     if (x == 11)
  2312.       x = sscanf(buf,"%d",&pid);    /* Get the integer pid from it. */
  2313. #else
  2314.     x = read(fd, (char *)&pid, sizeof(pid)); /* Else read integer pid */
  2315. #endif /* PIDSTRING */
  2316.  
  2317.     if (x < 0) pid = -1;        /* Return any errors. */
  2318.     close(fd);            /* Close the lockfile. */
  2319.     } else pid = -1;
  2320.     return(pid);
  2321. }
  2322.  
  2323. /*  T T L O C K  */
  2324.  
  2325. /*
  2326.   This function attempts to coordinate use of the communication device with
  2327.   other copies of Kermit and any other program that follows the UUCP
  2328.   device-locking conventions, which, unfortunately, vary among different UNIX
  2329.   implementations.  The idea is to look for a file of a certain name, the
  2330.   "lockfile", in a certain directory.  If such a file is found, then the line
  2331.   is presumed to be in use, and Kermit should not use it.  If no such file is
  2332.   found, Kermit attempts to create one so that other programs will not use the
  2333.   same line at the same time.  Because the lockfile and/or the directory it's
  2334.   in might lack write permission for the person running Kermit, Kermit could
  2335.   find itself running setuid to uucp or other user that does have the
  2336.   necessary permissions.  At startup, Kermit has changed its effective uid to
  2337.   the user's real uid, and so ttlock() must switch back to the original
  2338.   effective uid in order to create the lockfile, and then back again to the
  2339.   real uid to prevent unauthorized access to other directories or files owned
  2340.   by the user the program is setuid to.
  2341.  
  2342.   Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
  2343.   based on suggestions from Warren Tucker.  Call with pointer to name of 
  2344.   tty device.  Returns:
  2345.  
  2346.    0 on success
  2347.   -1 on failure
  2348.  
  2349.   Note: Once privileges are turned on using priv_on(), it is essential that
  2350.   they are turned off again before this function returns.
  2351. */
  2352. #ifdef SVR4                /* Lockfile uses device numbers. */
  2353. #ifndef LFDEVNO                /* Define this for SVR4 */
  2354. #ifndef AIXRS                /* But not for RS/6000 AIX 3.2 */
  2355. #define LFDEVNO                /* If anybody else needs it, */
  2356. #endif /* AIXRS */
  2357. #endif /* LFDEVNO */            /* define it here or on CC */
  2358. #endif /* SVR4 */            /* command line. */
  2359.  
  2360. #ifdef COHERENT
  2361. #define LFDEVNO
  2362. #endif /* COHERENT */
  2363.  
  2364. #ifdef LFDEVNO
  2365. #include <sys/stat.h>            /* For major() & minor() macros. */
  2366.                     /* Should be in <sys/types.h>. */
  2367. #ifndef major                /* If we didn't find it */
  2368. #ifdef SVR4                /* then for Sys V R4 */
  2369. #include <sys/mkdev.h>            /* look here */
  2370. #else                    /* or for Sunos versions */
  2371. #ifdef SUNOS4                /* ... */
  2372. #include <sys/sysmacros.h>        /* look here */
  2373. #else                    /* Otherwise take a chance: */
  2374. #define    major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
  2375. #define    minor(dev) ( (int) ( (dev) & 0xff))
  2376. #endif /* SUNOS4 */
  2377. #endif /* SVR4 */
  2378. #endif /* major */
  2379. #endif /* LFDEVNO */
  2380. /*
  2381.   Note for RS/6000: routines ttylock(devicename), ttyunlock(devicename),
  2382.   and ttylocked(devicename) from the standard library (libc.a) could be 
  2383.   used here instead.  It's not clear whether there is any advantage in this.
  2384. */
  2385. static int
  2386. ttlock(ttdev) char *ttdev; {
  2387.     int x;
  2388.  
  2389. #ifdef MINIX
  2390.     char *buf;
  2391. #endif /* MINIX */
  2392.  
  2393. #ifdef NOUUCP
  2394.     strcpy(flfnam,"NOLOCK");
  2395.     haslock = 1;
  2396.     return(0);
  2397. #else /* !NOUUCP */
  2398.     int lockfd;                /* File descriptor for lock file. */
  2399.     PID_T pid;                /* Process id of this process. */
  2400.     int fpid;                /* pid found in existing lockfile. */
  2401.     int tries;                /* How many times we've tried... */
  2402. #ifdef LFDEVNO
  2403.     struct stat devbuf;            /* For device numbers (SVR4). */
  2404. #endif /* LFDEVNO */
  2405.  
  2406. #ifdef PIDSTRING
  2407.     char pid_str[12];            /* My pid in string format. */
  2408. #endif /* PIDSTRING */
  2409.  
  2410.     char *device, *devname;
  2411.  
  2412. #define LFNAML 50            /* Max length for lock file name. */
  2413.     char lockfil[LFNAML];        /* Lock file name */
  2414. #ifdef RTAIX
  2415.     char lklockf[LFNAML];        /* Name for link to lock file  */
  2416. #endif /* RTAIX */
  2417.     char tmpnam[LFNAML+30];        /* Temporary lockfile name. */
  2418.     char *lockdir = LOCK_DIR;        /* Defined near top of this file, */
  2419.                     /* or on cc command line. */
  2420.  
  2421.     haslock = 0;                        /* Not locked yet. */
  2422.     *flfnam = '\0';            /* Lockfile name is empty. */
  2423.     pid = getpid();            /* Get id of this process. */
  2424.  
  2425. /*  Construct name of lockfile and temporary file */
  2426.  
  2427. /*  device  = name of tty device without the path, e.g. "ttyh8" */
  2428. /*  lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
  2429.  
  2430.     device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
  2431.  
  2432. #ifdef ISIII                /* Interactive System III, PC/IX */
  2433.     strcpy(lockfil, device);
  2434. #else
  2435. #ifdef LFDEVNO                /* Lockfilename has device numbers. */
  2436.     if (stat(ttdev,&devbuf) < 0)
  2437.       return(-1);
  2438. #ifdef COHERENT
  2439.     sprintf(lockfil,"LCK..%d.%d",
  2440.         major(devbuf.st_rdev),       /* major device number */
  2441.         0x1f & minor(devbuf.st_rdev)); /* minor device number */
  2442. #else
  2443.     sprintf(lockfil,"LK.%03d.%03d.%03d",
  2444.         major(devbuf.st_dev),    /* inode */
  2445.         major(devbuf.st_rdev),    /* major device number */
  2446.         minor(devbuf.st_rdev));    /* minor device number */
  2447. #endif /* COHERENT */
  2448. #else                    /* Others... */
  2449. #ifdef PTX                /* Dynix PTX */
  2450.     if (device != &ttdev[5] && strncmp(ttdev,"/dev/",5)==0) {
  2451.     sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
  2452.     } else
  2453. #endif /* PTX */
  2454.     sprintf(lockfil,"LCK..%s", device);
  2455. #ifdef M_XENIX                /* SCO Xenix */
  2456.     { int x; char c;
  2457.       x = (int)strlen(lockfil) - 1;    /* Get last letter of device name. */
  2458.       if (x > 0) {            /* If it's uppercase, lower it. */
  2459.       c = lockfil[x];
  2460.       if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
  2461.       }
  2462.     }
  2463. #endif /* M_XENIX */
  2464. #ifdef RTAIX
  2465.     strcpy(lklockf,device);
  2466. #endif /* RTAIX */
  2467. #endif /* LFDEVNO */
  2468. #endif /* ISIII */
  2469.  
  2470. /*  flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
  2471. /*  tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
  2472.  
  2473.     sprintf(flfnam,"%s/%s",lockdir,lockfil);
  2474. #ifdef RTAIX
  2475.     sprintf(lkflfn,"%s/%s",lockdir,lklockf);
  2476. #endif /* RTAIX */
  2477.     sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid);
  2478.     debug(F110,"ttlock flfnam",flfnam,0);
  2479.     debug(F110,"ttlock tmpnam",tmpnam,0);
  2480.  
  2481.     priv_on();                /* Turn on privileges if possible. */
  2482.     lockfd = creat(tmpnam, 0444);    /* Try to create temp lock file. */
  2483.     if (lockfd < 0) {            /* Create failed. */
  2484.     debug(F111,"ttlock creat failed",tmpnam,errno);
  2485.     if (errno == ENOENT) {
  2486.         perror(lockdir);        
  2487.         printf("UUCP not installed or Kermit misconfigured\n");
  2488.     } else {
  2489.         perror(lockdir);
  2490.         unlink(tmpnam);        /* Get rid of the temporary file. */
  2491.     }
  2492.     priv_off();            /* Turn off privileges!!! */
  2493.     return(-1);            /* Return failure code. */
  2494.     }
  2495. /* Now write the pid into the temp lockfile in the appropriate format */
  2496.  
  2497. #ifdef PIDSTRING            /* For Honey DanBer UUCP, */
  2498. #ifdef COHERENT
  2499.     sprintf(pid_str,"%d\n", (int) pid); /* Write pid as decimal string. */
  2500.     write(lockfd, pid_str, strlen (pid_str));
  2501. #else
  2502.     sprintf(pid_str,"%10d\n", (int) pid); /* Write pid as decimal string. */
  2503.     write(lockfd, pid_str, 11);
  2504. #endif /* COHERENT */
  2505.     debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
  2506. #else                    /* Others use integer pid */
  2507.     write(lockfd, (char *)&pid, sizeof(pid) );
  2508.     debug(F111,"ttlock pid","",(int) pid);
  2509. #endif /* PIDSTRING */
  2510.  
  2511. /* Now try to rename the temp file to the real lock file name. */
  2512. /* This will fail if a lock file of that name already exists.  */
  2513.  
  2514.     close(lockfd);            /* Close the temp lockfile. */
  2515.     chmod(tmpnam,0444);            /* Permission for a valid lock. */    
  2516.     tries = 0;
  2517.     while (!haslock && tries++ < 2) {
  2518.     haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
  2519.     if (haslock) {                  /* If we got the lockfile */
  2520. #ifdef RTAIX
  2521.         link(flfnam,lkflfn);
  2522. #endif /* RTAIX */ 
  2523. #ifdef LOCKF
  2524. /*
  2525.   Advisory file locking works on SVR4, so we use it.  In fact, it is
  2526.   necessary in some cases, e.g. when SLIP is involved.
  2527. */
  2528.             while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
  2529.                 debug(F111, "ttlock: lockf returns errno", "", errno);
  2530.                 if ( (++tries >= 3) || (errno != EAGAIN) ) {
  2531.                     x = unlink(flfnam); /* remove the lockfile */
  2532.                     debug(F111,"ttlock unlink",flfnam,x);
  2533.                     haslock = 0;
  2534.             break;
  2535.         }
  2536.                 sleep(2);
  2537.         }
  2538.         if (haslock)        /* If we got an advisory lock */
  2539. #endif /* LOCKF */
  2540.           break;            /* We're done. */
  2541.  
  2542.     } else {            /* We didn't create a new lockfile. */
  2543.         if ((fpid = ttrpid(flfnam)) > -1) {    /* Read pid from old one. */
  2544.         if (fpid > 0) {
  2545.             debug(F101,"ttlock fpid","",fpid);
  2546.             errno = 0;        /* See if process still exists. */
  2547.             x = kill((PID_T) fpid,0);
  2548.             debug(F101,"ttlock kill","",x);
  2549.             debug(F101,"ttlock kill errno","",errno);
  2550.             if (x < 0 && errno == ESRCH) { /* pid is invalid */
  2551.             debug(F111,"ttlock removing stale lock",flfnam,
  2552.                   fpid);
  2553.             if (!backgrd)
  2554.               printf(
  2555.                 "Removing stale lock %s (pid %d terminated)\n",
  2556.                  flfnam,fpid);
  2557.             x = unlink(flfnam); /* remove the lockfile. */
  2558.             debug(F111,"ttlock unlink",flfnam,x);
  2559.             continue;    /* and go back and try again. */
  2560.             } else if ((x < 0 && errno == EPERM) || x == 0) {
  2561.             unlink(tmpnam);    /* Delete the tempfile */
  2562.             debug(F101,"ttlock found tty locked","",fpid);
  2563.             priv_off();    /* Turn off privs */
  2564.             return(-2);    /* Code for device is in use. */
  2565.             }
  2566.         } else {
  2567.             debug(F101,"ttlock can't get fpid","",fpid);
  2568.             break;
  2569.         }
  2570.         } else break;        /* Couldn't read pid from old file */
  2571.     }
  2572.     }
  2573.     unlink(tmpnam);            /* Unlink (remove) the temp file. */
  2574.     priv_off();                /* Turn off privs */
  2575.     return(haslock ? 0 : -1);        /* Return link's return code. */
  2576. #endif /* !NOUUCP */
  2577. }
  2578.  
  2579. /*  T T U N L O C K  */
  2580.  
  2581. static int
  2582. ttunlck() {                             /* Remove UUCP lockfile. */
  2583. #ifndef NOUUCP
  2584.     if (haslock && *flfnam) {
  2585.     priv_on();            /* Turn privileges on.  */
  2586.     unlink(flfnam);            /* Remove the lockfile. */
  2587. #ifdef RTAIX
  2588.     unlink(lkflfn);            /* Remove other lockfile */
  2589. #endif /* RTAIX */
  2590. #ifdef LOCKF
  2591.         (void) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
  2592. #endif /* LOCKF */
  2593.     *flfnam = '\0';            /* Erase the name. */
  2594.     priv_off();            /* Turn privileges off. */
  2595.     }
  2596. #endif /* !NOUUCP */
  2597.     return(0);
  2598. }
  2599.  
  2600. /* 4.3BSD-style UUCP line direction control (Stan Barber, Rice U) */
  2601.  
  2602. #ifdef ACUCNTRL
  2603. VOID
  2604. acucntrl(flag,ttname) char *flag, *ttname; {
  2605.     char x[DEVNAMLEN+32], *device, *devname;
  2606.  
  2607.     if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
  2608.       return;                /* just return. */
  2609.     device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
  2610.     if (strncmp(device,"LCK..",4) == 0) device += 5;
  2611.     sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device);
  2612.     debug(F110,"called ",x,0);
  2613.     zsyscmd(x);
  2614. }
  2615. #endif /* ACUCNTRL */
  2616.  
  2617. /*
  2618.   T T H F L O W  --  Set hardware flow control.
  2619. */
  2620. static int
  2621. tthflow(flow) int flow; {
  2622.     int x = 0;                /* Return code */
  2623.  
  2624. /* There is no hardware flow control in POSIX. */
  2625.  
  2626. #ifndef OXOS
  2627. /*
  2628.   For SunOS 4.0 and later in the BSD environment ...
  2629.  
  2630.   The declarations are copied and interpreted from the System V header files,
  2631.   so we don't actually have to pull in all the System V junk when building
  2632.   C-Kermit for SunOS in the BSD environment, which would be dangerous because
  2633.   having those symbols defined would cause us to take the wrong paths through
  2634.   the code.  The code in this section is used in both the BSD and Sys V SunOS
  2635.   versions.
  2636. */
  2637. #ifdef SUNOS41
  2638. /*
  2639.   In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
  2640.   because GNU CC uses different formats for the _IOxxx macros than regular CC;
  2641.   the POSIX forms work for both.  But the POSIX calls are not available in
  2642.   SunOS 4.0.
  2643. */
  2644. #define CRTSCTS 0x80000000        /* RTS/CTS flow control */
  2645. #define TCSANOW 0            /* Do it now */
  2646.  
  2647.     struct termios {
  2648.     unsigned long c_iflag;        /* Input modes */
  2649.     unsigned long c_oflag;        /* Output modes */
  2650.     unsigned long c_cflag;        /* Control modes */
  2651.     unsigned long c_lflag;        /* Line discipline modes */
  2652.     char c_line;
  2653.     CHAR c_cc[17];
  2654.     };
  2655.     struct termios temp;
  2656.  
  2657. _PROTOTYP( int tcgetattr, (int, struct termios *) );
  2658. _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
  2659.  
  2660. /*
  2661.   When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
  2662.   asserted.  So we don't set CRTSCTS unless CD is up.  This should be OK,
  2663.   since we don't need RTS/CTS during dialing, and after dialing is complete,
  2664.   we should have CD.  If not, we still communicate, but without RTS/CTS.
  2665. */
  2666.       int mflags;                    /* Modem signal flags */
  2667.       if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
  2668.           (mflags & TIOCM_CAR)) {            /* Check for CD */
  2669.           debug(F100,"tthflow SunOS has CD","",0);
  2670.           if (tcgetattr(ttyfd, &temp) > -1 &&   /* Get device attributes */
  2671.           !(temp.c_cflag & CRTSCTS)) {        /* Check for RTS/CTS */
  2672.           temp.c_cflag |= CRTSCTS;        /* Not there, add it */
  2673.           x = tcsetattr(ttyfd,TCSANOW,&temp);
  2674.           }
  2675.       } else debug(F100,"tthflow SunOS no CD","",0);
  2676. #else
  2677. #ifdef SUNOS4
  2678. /*
  2679.   SunOS 4.0 (and maybe earlier?).  This code is dangerous because it
  2680.   prevents compilation with GNU gcc, which uses different formats for the
  2681.   _IORxxx macros than regular cc.  SunOS 4.1 and later can use the POSIX
  2682.   routines in the #else part of this clause, which work for both cc and gcc.
  2683. */
  2684. #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
  2685. #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
  2686. #define CRTSCTS 0x80000000          /* RTS/CTS flow control */
  2687.  
  2688.     struct termios {
  2689.     unsigned long c_iflag;        /* Input modes */
  2690.     unsigned long c_oflag;        /* Output modes */
  2691.     unsigned long c_cflag;        /* Control modes */
  2692.     unsigned long c_lflag;        /* Line discipline modes */
  2693.     char c_line;
  2694.     CHAR c_cc[17];
  2695.     };
  2696.     struct termios temp;
  2697.  
  2698.     if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get current terminal modes. */
  2699.     temp.c_cflag |= CRTSCTS;    /* Add RTS/CTS to them. */
  2700.     x = ioctl(ttyfd,TCSETS,&temp);    /* Set them again. */
  2701.     }
  2702. #else                    /* Not SunOS 4.0 or later */
  2703. #ifdef AIXRS
  2704.     if (ioctl(ttyfd, TXDELCD, "xon") < 0 && errno != EINVAL)
  2705.       debug(F100,"hardflow TXDELCD (xon) error", "", 0);
  2706.     if (ioctl(ttyfd, TXADDCD, "rts") < 0 && errno != EBUSY)
  2707.       debug(F100,"hardflow TXADDCD (rts) error", "", 0);
  2708. #else                    /* Not AIX RS/6000 */
  2709. #ifdef ATTSV
  2710.     if (flow == FLO_RTSC) {
  2711.     /* RTS/CTS Flow control... */
  2712. #ifdef RTSXOFF
  2713.     /* This is the preferred way, according to SVID R4 */
  2714.     if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
  2715.         rctsx.x_hflag |= RTSXOFF | CTSXON;
  2716.         x = ioctl(ttyfd,TCSETX,&rctsx);
  2717.     }
  2718. #endif /* RTSXOFF */
  2719.     }
  2720.     if (flow == FLO_DTRC) {
  2721.     /* DTR/CD Flow control... */
  2722. #ifdef DTRXOFF
  2723.     /* This is straight out of SVID R4 */
  2724.     if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
  2725.         rctsx.x_hflag |= DTRXOFF | CDXON;
  2726.         x = ioctl(ttyfd,TCSETX,&rctsx);
  2727.     }
  2728. #endif /* DTRXOFF */
  2729.     }
  2730. #else /* not System V */
  2731. #ifdef CK_DTRCTS
  2732.     x = LDODTR | LDOCTS;        /* Found only on UTEK? */
  2733.     if (flow == FLO_DTRT) {        /* Use hardware flow control */
  2734.     if (lmodef) {
  2735.         x = ioctl(ttyfd,TIOCLBIS,&x);
  2736.         if (x < 0) {
  2737.             debug(F100,"hardflow TIOCLBIS error","",0);
  2738.         } else {
  2739.         lmodef++;
  2740.         debug(F100,"hardflow TIOCLBIS ok","",0);
  2741.         }
  2742.     }
  2743.     } else {
  2744.     if (lmodef) {
  2745.         x = ioctl(ttyfd,TIOCLBIC,&x);
  2746.         if (x < 0) {
  2747.             debug(F100,"hardflow TIOCLBIC error","",0);
  2748.         } else {
  2749.         lmodef++;
  2750.         debug(F100,"hardflow TIOCLBIC ok","",0);
  2751.         }
  2752.     }
  2753.     }
  2754. #endif /* CK_DTRCTS */
  2755. #endif /* ATTSV */
  2756. #endif /* AIXRS */
  2757. #endif /* SUNOS4 */
  2758. #endif /* SUNOS41 */
  2759. #else /* OXOS */
  2760.     struct termios temp;
  2761.  
  2762.     x = ioctl(ttyfd,TCGETS,&temp);
  2763.     if (x == 0) {
  2764.     temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
  2765.     switch (flow) {
  2766.     case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
  2767.         break;
  2768.     case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
  2769.         break;
  2770.     }
  2771.     x = ioctl(ttyfd,TCSETS,&temp);
  2772.     }
  2773. #endif /* OXOS */
  2774.     return(x);
  2775. }
  2776.  
  2777. /*  T T P K T  --  Condition the communication line for packets */
  2778. /*                 or for modem dialing */
  2779.  
  2780. /*
  2781.   If called with speed > -1, also set the speed.
  2782.   Returns 0 on success, -1 on failure.
  2783.  
  2784.   NOTE: the "xflow" parameter is supposed to be the currently selected
  2785.   type of flow control, but for historical reasons, this parameter is also
  2786.   used to indicate that we are dialing.  Therefore, when the true flow
  2787.   control setting is needed, we access the external variable "flow", rather
  2788.   than trusting our "xflow" argument.
  2789. */
  2790. int
  2791. #ifdef CK_ANSIC
  2792. ttpkt(long speed, int xflow, int parity)
  2793. #else
  2794. ttpkt(speed,xflow,parity) long speed; int xflow, parity;
  2795. #endif /* CK_ANSIC */
  2796. /* ttpkt */ {
  2797.     int s2;
  2798.     int s = -1;
  2799. #ifndef SVORPOSIX
  2800.     int x;
  2801. #endif /* SVORPOSIX */
  2802.     extern int flow;            /* REAL flow-control setting */
  2803.  
  2804.     if (ttyfd < 0) return(-1);          /* Not open. */
  2805.  
  2806.     debug(F101,"ttpkt parity","",parity);
  2807.     debug(F101,"ttpkt xflow","",xflow);
  2808.     debug(F101,"ttpkt speed","",(int) speed);
  2809.  
  2810.     ttprty = parity;                    /* Let other tt functions see these. */
  2811.     ttpflg = 0;                /* Parity not sensed yet */
  2812.     ttpmsk = ttprty ? 0177 : 0377;    /* Parity stripping mask */
  2813.     ttspeed = speed;            /* Make global copy for this module */
  2814.  
  2815. #ifdef NETCONN                /* Nothing to do for telnet */
  2816.     if (netconn) return (0);
  2817. #endif /* NETCONN */
  2818.  
  2819.     if (ttfdflg && !isatty(ttyfd)) return(0);
  2820.  
  2821. #ifndef SVORPOSIX            /* Berkeley, V7, etc. */
  2822. #ifdef LPASS8
  2823. /*
  2824.  For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
  2825.  after having previously set it to NONE without closing and reopening the
  2826.  device.  Unless there's something I overlooked below...
  2827. */
  2828.     if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
  2829.     debug(F101,"ttpkt executing horrible flow kludge","",0);
  2830.     ttclos(0);            /* Close it */
  2831.     x = 0;
  2832.     ttopen(ttnmsv,&x,ttmdm,0);    /* Open it again */
  2833.     }
  2834. #endif /* LPASS8 */
  2835. #endif /* SVORPOSIX */
  2836.  
  2837.     if (xflow != FLO_DIAL && xflow != FLO_DIAX)
  2838.       ttflow = xflow;            /* Now make this available too. */
  2839.  
  2840.     if (xlocal) {
  2841.     s2 = (int) (speed / 10L);    /* Convert bps to cps */
  2842.     s = ttsspd(s2);            /* Check and set the speed */
  2843.     debug(F101,"ttpkt carrier","",xflow);
  2844.      carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
  2845.         && (ttcarr == CAR_ON));
  2846.     tvtflg = 0;            /* So ttvt() will work next time */
  2847.     }
  2848.  
  2849. #ifndef SVORPOSIX            /* BSD section */
  2850.     if (flow == FLO_RTSC ||        /* Hardware flow control */
  2851.     flow == FLO_DTRC ||
  2852.     flow == FLO_DTRT) {
  2853.     tthflow(flow);
  2854.     debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
  2855.     ttraw.sg_flags &= ~TANDEM;    /* Don't ask for it. */
  2856.     ttraw.sg_flags |= RAW;
  2857.     } else if (flow == FLO_NONE) {    /* No Xon/Xoff flow control */
  2858.     debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
  2859.     ttraw.sg_flags &= ~TANDEM;    /* Don't ask for it. */
  2860.     ttraw.sg_flags |= RAW;
  2861. /* NOTE: We should also turn off hardware flow control here! */
  2862.     } else if (flow == FLO_KEEP) {    /* Keep device's original setting */
  2863.     debug(F100,"ttpkt keeping original TANDEM","",0);
  2864.     ttraw.sg_flags &= ~TANDEM;
  2865.     ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
  2866. /* NOTE: We should also handle hardware flow control here! */
  2867.     }
  2868.  
  2869. /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
  2870.  
  2871.     if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
  2872.     debug(F100,"ttpkt turning on TANDEM","",0);
  2873.     ttraw.sg_flags |= TANDEM;    /* So ask for it. */
  2874.  
  2875. #ifdef LPASS8                /* Can pass 8-bit data through? */
  2876. /* If the LPASS8 local mode is available, then flow control can always  */
  2877. /* be used, even if parity is none and we are transferring 8-bit data.  */
  2878. /* But we only need to do all this if Xon/Xoff is requested. */
  2879. /* BUT... this tends not to work through IP or LAT connections, terminal */
  2880. /* servers, telnet, rlogin, etc, so it is currently disabled. */
  2881.     x = LPASS8;            /* If LPASS8 defined, then */
  2882.     debug(F100,"ttpkt executing LPASS8 code","",0);
  2883.     if (lmodef) {            /* TIOCLBIS must be too. */
  2884.         x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
  2885.         if (x < 0) {
  2886.         debug(F100,"ttpkt TIOCLBIS error","",0);
  2887.         } else {
  2888.         lmodef++;
  2889.         debug(F100,"ttpkt TIOCLBIS ok","",0);
  2890.         }
  2891.     }
  2892. /*
  2893.  But if we use LPASS8 mode, we must explicitly turn off
  2894.  terminal interrupts of all kinds.
  2895. */
  2896. #ifdef TIOCGETC                /* Not rawmode, */
  2897.     if (tcharf && (xlocal == 0)) {    /* must turn off */
  2898.         tchnoi.t_intrc = -1;    /* interrupt character */
  2899.         tchnoi.t_quitc = -1;    /* and quit character. */
  2900.         tchnoi.t_startc = 17;    /* Make sure xon */
  2901.         tchnoi.t_stopc = 19;    /* and xoff not ignored. */
  2902. #ifndef NOBRKC
  2903.         tchnoi.t_eofc = -1;        /* eof character. */ 
  2904.         tchnoi.t_brkc = -1;        /* brk character. */ 
  2905. #endif /* NOBRKC */
  2906.         if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
  2907.         debug(F100,"ttpkt TIOCSETC failed","",0);
  2908.         } else {
  2909.         tcharf = 1;
  2910.         debug(F100,"ttpkt TIOCSETC ok","",0);
  2911.         }
  2912. #ifdef COMMENT
  2913. /* only for paranoid debugging */
  2914.         if (tcharf) {
  2915.         struct tchars foo;
  2916.         char tchbuf[100];
  2917.         ioctl(0,TIOCGETC,&foo);
  2918.         sprintf(tchbuf,
  2919.             "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
  2920.             foo.t_intrc, foo.t_quitc, foo.t_startc,
  2921.             foo.t_stopc, foo.t_eofc,  foo.t_brkc);
  2922.         debug(F110,"ttpkt chars",tchbuf,0);
  2923.         }
  2924. #endif /* COMMENT */
  2925.     }
  2926.     ttraw.sg_flags |= CBREAK;    /* Needed for unknown reason */
  2927. #endif /* TIOCGETC */
  2928.  
  2929. /* Prevent suspend during packet mode */
  2930. #ifdef TIOCGLTC                /* Not rawmode, */
  2931.     if (ltcharf && (xlocal == 0)) {    /* must turn off */
  2932.         ltchnoi.t_suspc = -1;    /* suspend character */
  2933.         ltchnoi.t_dsuspc = -1;    /* and delayed suspend character */
  2934.         if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
  2935.         debug(F100,"ttpkt TIOCSLTC failed","",0);
  2936.         } else {
  2937.         ltcharf = 1;
  2938.         debug(F100,"ttpkt TIOCSLTC ok","",0);
  2939.         }
  2940.     }
  2941. #endif /* TIOCGLTC */
  2942.  
  2943. #else /* LPASS8 not defined */
  2944.  
  2945. /* Previously, BSD-based implementations always */
  2946. /* used rawmode for packets.  Now, we use rawmode only if parity is NONE. */
  2947. /* This allows the flow control requested above to actually work, but only */
  2948. /* if the user asks for parity (which also means they get 8th-bit quoting). */
  2949.  
  2950.     if (parity) {            /* If parity, */
  2951.         ttraw.sg_flags &= ~RAW;    /* use cooked mode */
  2952. #ifdef COMMENT
  2953. /* WHY??? */
  2954.         if (xlocal)
  2955. #endif /* COMMENT */
  2956.           ttraw.sg_flags |= CBREAK;
  2957.         debug(F101,"ttpkt cooked, cbreak, parity","",parity);
  2958. #ifdef TIOCGETC                /* Not rawmode, */
  2959.         if (tcharf && (xlocal == 0)) { /* must turn off */
  2960.         tchnoi.t_intrc = -1;    /* interrupt character */
  2961.         tchnoi.t_quitc = -1;    /* and quit character. */
  2962.         tchnoi.t_startc = 17;    /* Make sure xon */
  2963.         tchnoi.t_stopc = 19;    /* and xoff not ignored. */
  2964. #ifndef NOBRKC
  2965.         tchnoi.t_eofc = -1;    /* eof character. */ 
  2966.         tchnoi.t_brkc = -1;    /* brk character. */ 
  2967. #endif /* NOBRKC */
  2968.         if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
  2969.             debug(F100,"ttpkt TIOCSETC failed","",0);
  2970.         } else {
  2971.             tcharf = 1;
  2972.             debug(F100,"ttpkt TIOCSETC ok","",0);
  2973.         }
  2974.         }
  2975. #endif /* TIOCGETC */
  2976. #ifdef TIOCGLTC                /* Not rawmode, */
  2977. /* Prevent suspend during packet mode */
  2978.         if (ltcharf && (xlocal == 0)) { /* must turn off */
  2979.         ltchnoi.t_suspc = -1;    /* suspend character */
  2980.         ltchnoi.t_dsuspc = -1;    /* and delayed suspend character */
  2981.         if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
  2982.             debug(F100,"ttpkt TIOCSLTC failed","",0);
  2983.         } else {
  2984.             ltcharf = 1;
  2985.             debug(F100,"ttpkt TIOCSLTC ok","",0);
  2986.         }
  2987.         }
  2988. #endif /* TIOCGLTC */
  2989.     } else {            /* If no parity, */
  2990.         ttraw.sg_flags |= RAW;    /* must use 8-bit raw mode. */
  2991.         debug(F101,"ttpkt setting rawmode, parity","",parity);
  2992.     }
  2993. #endif /* LPASS8 */
  2994.     } /* End of Xon/Xoff section */
  2995.  
  2996.     /* Don't echo, don't map CR to CRLF on output, don't fool with case */
  2997. #ifdef LCASE
  2998.     ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
  2999. #else
  3000.     ttraw.sg_flags &= ~(ECHO|CRMOD);
  3001. #endif /* LCASE */
  3002.  
  3003. #ifdef TOWER1
  3004.     ttraw.sg_flags &= ~ANYP;            /* Must set this on old Towers */
  3005. #endif /* TOWER1 */
  3006.  
  3007.     if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */
  3008.     debug(F100,"ttpkt stty ok","",0);
  3009.  
  3010. #ifdef sony_news
  3011.     x = xlocal ? km_ext : km_con;    /* Put line in ASCII mode. */
  3012.     if (x != -1) {            /* Make sure we know original modes. */
  3013.     x &= ~KM_TTYPE;
  3014.     x |= KM_ASCII;
  3015.     if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
  3016.         perror("ttpkt can't set ASCII mode");
  3017.         debug(F101,"ttpkt error setting ASCII mode","",x);
  3018.         return(-1);
  3019.     }
  3020.     }
  3021.     debug(F100,"ttpkt set ASCII mode ok","",0);
  3022. #endif /* sony_news */
  3023.  
  3024.     if (xlocal == 0)            /* Turn this off so we can read */
  3025.       signal(SIGINT,SIG_IGN);        /* Ctrl-C chars typed at console */
  3026.  
  3027.     tvtflg = 0;                /* So ttvt() will work next time */
  3028.     return(0);
  3029.  
  3030. #endif /* Not ATTSV or POSIX */
  3031.  
  3032. /* AT&T UNIX and POSIX */
  3033.  
  3034. #ifdef SVORPOSIX
  3035.     if (flow == FLO_XONX) {        /* Xon/Xoff */
  3036.     ttraw.c_iflag |= (IXON|IXOFF);
  3037. #ifdef AIXRS
  3038.       if (ioctl(ttyfd, TXDELCD, "rts") < 0 && errno != EINVAL)
  3039.     return(-1);
  3040.       if (ioctl(ttyfd, TXADDCD, "xon") < 0 && errno != EBUSY)
  3041.     return(-1);
  3042. #endif /* AIXRS */
  3043.     } else if (flow == FLO_NONE)    /* None */
  3044.       /* NOTE: We should also turn off hardware flow control here! */
  3045.       ttraw.c_iflag &= ~(IXON|IXOFF);
  3046.     else if (flow == FLO_KEEP) {    /* Keep */
  3047.     ttraw.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff flags */
  3048.     ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  3049.     /* NOTE: We should also handle hardware flow control here! */
  3050.     } else if (flow == FLO_RTSC ||    /* Hardware */
  3051.     flow == FLO_DTRC ||
  3052.     flow == FLO_DTRT)
  3053.       tthflow(flow);
  3054.  
  3055.     ttraw.c_lflag &= ~(ICANON|ECHO);
  3056.     ttraw.c_lflag &= ~ISIG;        /* Do NOT check for interrupt chars */
  3057. #ifndef OXOS
  3058.     ttraw.c_lflag &= ~IEXTEN;        /* Turn off ^O/^V processing */
  3059. #else /* OXOS */
  3060.     ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
  3061. #endif /* OXOS */
  3062.     ttraw.c_lflag |= NOFLSH;        /* Don't flush */
  3063.     ttraw.c_iflag |= (BRKINT|IGNPAR);
  3064. #ifdef ATTSV
  3065. #ifdef BSD44
  3066.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
  3067. #else
  3068.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
  3069. #endif /* BSD44 */
  3070. #else /* POSIX */
  3071.     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
  3072. #endif /* ATTSV */
  3073.     ttraw.c_oflag &= ~OPOST;
  3074.     ttraw.c_cflag &= ~(CSIZE|PARENB);
  3075.     ttraw.c_cflag |= (CS8|CREAD|HUPCL);
  3076. #ifdef IX370
  3077.     ttraw.c_cc[4] = 48;  /* So Series/1 doesn't interrupt on every char */
  3078.     ttraw.c_cc[5] = 1;
  3079. #else
  3080. #ifndef VEOF    /* for DGUX this is VEOF, not VMIN */
  3081.     ttraw.c_cc[4] = 1;   /* [VMIN]  return max of this many characters or */
  3082. #else
  3083. #ifndef OXOS
  3084. #ifdef VMIN
  3085.     ttraw.c_cc[VMIN] = 1;
  3086. #endif /* VMIN */
  3087. #else /* OXOS */
  3088.     ttraw.c_min = 1;
  3089. #endif /* OXOS */
  3090. #endif /* VEOF */
  3091. #ifndef VEOL    /* for DGUX this is VEOL, not VTIME */
  3092.     ttraw.c_cc[5] = 0;     /* [VTIME] when this many secs/10 expire w/no input */
  3093. #else
  3094. #ifndef OXOS
  3095. #ifdef VTIME
  3096.     ttraw.c_cc[VTIME] = 0;
  3097. #endif /* VTIME */
  3098. #else /* OXOS */
  3099.     ttraw.c_time = 0;
  3100. #endif /* OXOS */
  3101. #endif /* VEOL */
  3102. #endif /* IX370 */
  3103.  
  3104. #ifdef VINTR                /* Turn off interrupt character */
  3105.     if (xlocal == 0)            /* so ^C^C can break us out of */
  3106.       ttraw.c_cc[VINTR] = 0;        /* packet mode. */
  3107. #endif /* VINTR */
  3108.  
  3109. #ifdef BSD44ORPOSIX
  3110.     if (xlocal && (s > 0)) {
  3111.     cfsetispeed(&ttraw,s);
  3112.     cfsetospeed(&ttraw,s);
  3113.     }
  3114.     if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0) return(-1);
  3115. #else /* ATTSV */
  3116.     if (xlocal && (s > 0)) {        /* set speed */
  3117.         ttraw.c_cflag &= ~CBAUD;
  3118. #ifdef OXOS
  3119.         ttraw.c_cflag &= ~CIBAUD;
  3120. #endif /* OXOS */
  3121.         ttraw.c_cflag |= s;
  3122.     }
  3123.     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1);  /* set new modes . */
  3124. #endif /* BSD44ORPOSIX */
  3125. #ifdef AIXRS
  3126.     if (flow == FLO_NONE) {
  3127.     if (ioctl(ttyfd, TXDELCD, "rts") < 0 && errno != EINVAL)
  3128.       return(-1);
  3129.     if (ioctl(ttyfd, TXDELCD, "xon") < 0 && errno != EINVAL)
  3130.       return(-1);
  3131.     }
  3132. #endif /* AIXRS */
  3133.     tvtflg = 0;
  3134.     return(0);
  3135. #endif /* ATTSV */
  3136. }
  3137.  
  3138. /*  T T V T -- Condition communication line for use as virtual terminal  */
  3139.  
  3140. int
  3141. #ifdef CK_ANSIC
  3142. ttvt(long speed, int flow)
  3143. #else
  3144. ttvt(speed,flow) long speed; int flow;
  3145. #endif /* CK_ANSIC */
  3146. /* ttvt */ {
  3147.     int s, s2;
  3148.  
  3149.     debug(F101,"ttvt ttyfd","",ttyfd);
  3150.     debug(F101,"ttvt tvtflg","",tvtflg);
  3151.     debug(F101,"ttvt speed","",speed);
  3152.     if (ttyfd < 0) return(-1);          /* Not open. */
  3153. #ifdef NETCONN
  3154.     if (netconn) {
  3155.     tvtflg = 1;            /* Network connections */
  3156.     return(0);            /* require no special setup */
  3157.     }
  3158. #endif /* NETCONN */
  3159.  
  3160.     if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr)
  3161.       return(0);            /* Already been called. */
  3162.  
  3163.     if (ttfdflg && !isatty(ttyfd)) return(0);
  3164.  
  3165.     if (xlocal) {            /* For external lines... */
  3166.     s2 = (int) (speed / 10L);
  3167.     s = ttsspd(s2);            /* Check/set the speed */
  3168.     carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
  3169.         && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
  3170.     } else s = s2 = -1;
  3171.  
  3172. #ifndef SVORPOSIX
  3173.     /* Berkeley, V7, etc */
  3174.     if (flow == FLO_RTSC ||        /* Hardware flow control */
  3175.     flow == FLO_DTRC ||
  3176.     flow == FLO_DTRT)
  3177.       tthflow(flow);
  3178.     if (flow == FLO_XONX) {        /* No Xon/Xoff flow control */
  3179.     tttvt.sg_flags |= TANDEM;    /* Ask for it. */
  3180.     } else if (flow == FLO_KEEP) {
  3181.     tttvt.sg_flags &= ~TANDEM;
  3182.     tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
  3183. /* NOTE: We should also handle hardware flow control here! */
  3184.     } else if (flow == FLO_NONE) {
  3185.     tttvt.sg_flags &= ~TANDEM;    /* Don't ask for it. */
  3186. /* NOTE: We should also turn off hardware flow control here! */
  3187.     }
  3188.     tttvt.sg_flags |= RAW;              /* Raw mode in all cases */
  3189. #ifdef TOWER1
  3190.     tttvt.sg_flags &= ~(ECHO|ANYP);     /* No echo or parity */
  3191. #else
  3192.     tttvt.sg_flags &= ~ECHO;            /* No echo */
  3193. #endif /* TOWER1 */
  3194.  
  3195.     if (stty(ttyfd,&tttvt) < 0)        /* Set the new modes */
  3196.       return(-1);
  3197.  
  3198. #else /* It is ATTSV or POSIX */
  3199.  
  3200.     if (flow == FLO_RTSC ||        /* Hardware flow control */
  3201.     flow == FLO_DTRC ||
  3202.     flow == FLO_DTRT)
  3203.       tthflow(flow);
  3204.     else if (flow == FLO_XONX) {    /* Software flow control */
  3205.     tttvt.c_iflag |= (IXON|IXOFF);    /* On if requested. */
  3206. #ifdef AIXRS
  3207.     if (ioctl(ttyfd, TXDELCD, "rts") < 0 && errno != EINVAL)
  3208.       return(-1);
  3209.     if (ioctl(ttyfd, TXADDCD, "xon") < 0 && errno != EBUSY)
  3210.       return(-1);
  3211. #endif /* AIXRS */
  3212.     } else if (flow == FLO_KEEP) {
  3213.     tttvt.c_iflag &= ~(IXON|IXOFF);    /* Turn off Xon/Xoff flags */
  3214.     tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
  3215.     /* NOTE: We should also handle hardware flow control here! */
  3216.     } else if (flow == FLO_NONE)    /* Off if NONE or hardware */
  3217.       tttvt.c_iflag &= ~(IXON|IXOFF);    /* requested. */
  3218.  
  3219. #ifndef OXOS
  3220.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
  3221. #else /* OXOS */
  3222.     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
  3223.     tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
  3224. #endif /* OXOS */
  3225.     tttvt.c_iflag |= (IGNBRK|IGNPAR);
  3226. #ifdef ATTSV
  3227. #ifdef BSD44
  3228.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|BRKINT|INPCK|ISTRIP|IXANY);
  3229. #else
  3230.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
  3231. #endif /* BSD44 */
  3232. #else /* POSIX */
  3233.     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|BRKINT|INPCK|ISTRIP);
  3234. #endif /* ATTSV */
  3235.     tttvt.c_oflag &= ~OPOST;
  3236.     tttvt.c_cflag &= ~(CSIZE|PARENB);
  3237.     tttvt.c_cflag |= (CS8|CREAD|HUPCL);
  3238. #ifndef VEOF    /* DGUX termio has VEOF at entry 4, see comment above */
  3239.     tttvt.c_cc[4] = 1;
  3240. #else
  3241. #ifndef OXOS
  3242. #ifdef VMIN
  3243.     tttvt.c_cc[VMIN] = 1;
  3244. #endif /* VMIN */
  3245. #else /* OXOS */
  3246.     tttvt.c_min = 1;
  3247. #endif /* OXOS */
  3248. #endif /* VEOF */
  3249. #ifndef VEOL    /* DGUX termio has VEOL at entry 5, see comment above */
  3250.     tttvt.c_cc[5] = 0;
  3251. #else
  3252. #ifndef OXOS
  3253. #ifdef VTIME
  3254.     tttvt.c_cc[VTIME] = 0;
  3255. #endif /* VTIME */
  3256. #else /* OXOS */
  3257.     tttvt.c_time = 0;
  3258. #endif /* OXOS */
  3259. #endif /* VEOL */
  3260.  
  3261. #ifdef BSD44ORPOSIX
  3262.     if (xlocal && (s > 0)) {
  3263.     cfsetispeed(&tttvt,s);
  3264.     cfsetospeed(&tttvt,s);
  3265.     }
  3266.     if (tcsetattr(ttyfd,TCSADRAIN,&tttvt) < 0) return(-1);
  3267. #else /* ATTSV */
  3268.     if (s > 0) {            /* Set speed */
  3269.         tttvt.c_cflag &= ~CBAUD;
  3270. #ifdef OXOS
  3271.         ttraw.c_cflag &= ~CIBAUD;
  3272. #endif /* OXOS */
  3273.         tttvt.c_cflag |= s;
  3274.     }
  3275.     if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1);  /* set new modes . */
  3276. #ifdef AIXRS
  3277.     if (flow == FLO_NONE) {
  3278.     if (ioctl(ttyfd, TXDELCD, "rts") < 0 && errno != EINVAL)
  3279.       return(-1);
  3280.     if (ioctl(ttyfd, TXDELCD, "xon") < 0 && errno != EINVAL)
  3281.       return(-1);
  3282.     }
  3283. #endif /* AIXRS */
  3284. #endif /* BSD44ORPOSIX */
  3285. #endif /* ATTSV */
  3286.  
  3287.     ttspeed = speed;            /* Done, remember how we were */
  3288.     ttflow = flow;            /* called, so we can decide how to */
  3289.     tvtflg = 1;                /* respond next time. */
  3290.  
  3291.     debug(F101,"ttvt done","",tvtflg);
  3292.     return(0);
  3293. }
  3294.  
  3295. /*  T T S S P D  --  Checks and sets transmission rate.  */
  3296.  
  3297. /*  Call with speed in characters (not bits!) per second. */
  3298. /*  Returns internal speed code if successful, -1 otherwise. */
  3299.  
  3300. int
  3301. ttsspd(cps) int cps; {
  3302. #ifdef QNX
  3303. /* Needed for 38400 on 16-bit architectures */
  3304. /* Maybe this is safe in general, but why take chances? */
  3305.     unsigned 
  3306. #endif /* QNX */
  3307.       int s, s2;
  3308.  
  3309.     debug(F101,"ttsspd","",cps);
  3310.  
  3311. #ifdef    NETCONN
  3312.     if (netconn) return (0);
  3313. #endif    /* NETCONN */
  3314.  
  3315.     if (cps < 0) return(-1);
  3316.     s = s2 = -1;
  3317.  
  3318.     /* First check that the given speed is valid. */
  3319.  
  3320.     switch (cps) {
  3321. #ifndef MINIX
  3322.       case 0:   s = B0;    break;
  3323.       case 5:   s = B50;   break;
  3324.       case 7:   s = B75;   break;
  3325. #endif /* MINIX */
  3326.       case 11:  s = B110;  break;
  3327. #ifndef MINIX
  3328.       case 15:  s = B150;  break;
  3329.       case 20:  s = B200;  break;
  3330. #endif /* MINIX */
  3331.       case 30:  s = B300;  break;
  3332. #ifndef MINIX
  3333.       case 60:  s = B600;  break;
  3334. #endif /* MINIX */
  3335.       case 120: s = B1200; break;
  3336. #ifndef MINIX
  3337.       case 180: s = B1800; break;
  3338. #endif /* MINIX */
  3339.       case 240: s = B2400; break;
  3340.       case 480: s = B4800; break;
  3341. #ifndef MINIX
  3342.       case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
  3343. #endif /* MINIX */
  3344.       case 960: s = B9600; break;
  3345. #ifdef B14400
  3346.       case 1440: s = B14400; break;
  3347. #endif /* B14400 */
  3348. #ifdef B19200
  3349.       case 1920: s = B19200; break;
  3350. #else
  3351. #ifdef EXTA
  3352.       case 1920: s = EXTA; break;
  3353. #endif /* EXTA */
  3354. #endif /* B19200 */
  3355. #ifdef B28800
  3356.       case 2880: s = B28800; break;
  3357. #endif /* B28800 */
  3358. #ifdef B38400
  3359.       case 3840: s = B38400; break;
  3360. #else
  3361. #ifdef EXTB
  3362.       case 3840: s = EXTB; break;
  3363. #endif /* EXTB */
  3364. #endif /* B38400 */
  3365.  
  3366. #ifdef HPUX
  3367. #ifdef _B57600
  3368.       case 5760: s = _B57600; break;
  3369. #endif /* _B57600 */
  3370. #ifdef _B115200
  3371.       case 11520: s = _B115200; break;
  3372. #endif /* _B115200 */
  3373. #else
  3374. #ifdef B57700
  3375.       case 5760: s = B57600; break;
  3376. #endif /* B57700 */
  3377. #endif /* HPUX */
  3378.  
  3379.       default:
  3380.     return(-1);
  3381.     }
  3382.     /* Actually set the speed */
  3383.  
  3384.     if (ttyfd > -1 && s > -1 && xlocal != 0) {
  3385.     if (s2 == -1) s2 = s;
  3386.  
  3387. #ifdef BSD44ORPOSIX
  3388.     if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
  3389.     cfsetospeed(&ttcur,s);
  3390.     cfsetispeed(&ttcur,s2);
  3391.     cfsetospeed(&ttraw,s);
  3392.     cfsetispeed(&ttraw,s2);
  3393.     cfsetospeed(&tttvt,s);
  3394.     cfsetispeed(&tttvt,s2);
  3395.     cfsetospeed(&ttold,s);
  3396.     cfsetispeed(&ttold,s2);
  3397.     if (tcsetattr(ttyfd,TCSADRAIN,&ttcur) < 0) return(-1);
  3398. #else
  3399. #ifdef ATTSV
  3400.     if (cps == 888) return(-1);    /* No split speeds, sorry. */
  3401.     if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1);
  3402.     ttcur.c_cflag &= ~CBAUD;
  3403.     ttcur.c_cflag |= s;
  3404.     tttvt.c_cflag &= ~CBAUD;
  3405.     tttvt.c_cflag |= s;
  3406.     ttraw.c_cflag &= ~CBAUD;
  3407.     ttraw.c_cflag |= s;
  3408.     ttold.c_cflag &= ~CBAUD;
  3409.     ttold.c_cflag |= s;
  3410.     if (ioctl(ttyfd,TCSETAW,&ttcur) < 0) return(-1);
  3411. #else
  3412.     if (gtty(ttyfd,&ttcur) < 0) return(-1);
  3413.     ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
  3414.     tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
  3415.     ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
  3416.     ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
  3417.     if (stty(ttyfd,&ttcur) < 0) return(-1);
  3418. #endif /* ATTSV */
  3419. #endif /* BSD44ORPOSIX */
  3420.     }
  3421.     return(s);
  3422. }
  3423.  
  3424. /* T T G S P D  -  Get speed of currently selected tty line  */
  3425.  
  3426. /*
  3427.   Unreliable.  After SET LINE, it returns an actual speed, but not the real
  3428.   speed.  Apparently it always returns the line's nominal speed, from
  3429.   /etc/ttytab.  Even if you SET SPEED to something else, this function might
  3430.   not notice.
  3431. */
  3432. long
  3433. ttgspd() {                /* Get current tty speed */
  3434.     int s; long ss;
  3435.     char temp[12];
  3436.  
  3437. #ifdef NETCONN
  3438.     if (netconn) return(-1);        /* -1 if network connection */
  3439. #endif /* NETCONN */
  3440.  
  3441.     if (ttyfd < 0) {
  3442. #ifdef BSD44ORPOSIX
  3443.     s = cfgetospeed(&ccold);
  3444. #else
  3445. #ifdef ATTSV
  3446.     s = ccold.c_cflag & CBAUD;
  3447. #else
  3448.     s = ccold.sg_ospeed;        /* (obtained by congm()) */
  3449. #endif /* ATTSV */
  3450. #endif /* BSD44ORPOSIX */
  3451.  
  3452.     } else {
  3453. #ifdef BSD44ORPOSIX
  3454.     if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
  3455.     s = cfgetospeed(&ttcur);
  3456. #else
  3457. #ifdef ATTSV
  3458.     if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1);
  3459.     s = ttcur.c_cflag & CBAUD;
  3460. #else
  3461.     if (gtty(ttyfd,&ttcur) < 0) return(-1);
  3462.     s = ttcur.sg_ospeed;
  3463. #endif /* ATTSV */
  3464. #endif /* BSD44ORPOSIX */
  3465.     }
  3466.     debug(F101,"ttgspd ttyfd","",ttyfd);
  3467.     debug(F101,"ttgspd code","",s);
  3468.     switch (s) {
  3469. #ifdef B0
  3470.       case B0:    ss = 0L; break;
  3471. #endif /* B0 */
  3472.  
  3473. #ifndef MINIX
  3474. /*
  3475.  MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
  3476.  etc, making for many "duplicate case in switch" errors, which are fatal.
  3477. */
  3478. #ifdef B50
  3479.       case B50:   ss = 50L; break;
  3480. #endif /* B50 */
  3481. #ifdef B75
  3482.       case B75:   ss = 75L; break;
  3483. #endif /* B75 */
  3484. #endif /* MINIX */
  3485.  
  3486. #ifdef B110
  3487.       case B110:  ss = 110L; break;
  3488. #endif /* B110 */
  3489.  
  3490. #ifndef MINIX
  3491. #ifdef B134
  3492.       case B134:  ss = 134L; break;
  3493. #endif /* B134 */
  3494. #ifdef B150
  3495.       case B150:  ss = 150L; break;
  3496. #endif /* B150 */
  3497. #endif /* MINIX */
  3498.  
  3499. #ifdef B200
  3500.       case B200:  ss = 200L; break;
  3501. #endif /* B200 */
  3502.  
  3503. #ifdef B300
  3504.       case B300:  ss = 300L; break;
  3505. #endif /* B300 */
  3506.  
  3507. #ifdef B600
  3508.       case B600:  ss = 600L; break;
  3509. #endif /* B600 */
  3510.  
  3511. #ifdef B1200
  3512.       case B1200: ss = 1200L; break;
  3513. #endif /* B1200 */
  3514.  
  3515. #ifdef B1800
  3516.       case B1800: ss = 1800L; break;
  3517. #endif /* B1800 */
  3518.  
  3519. #ifdef B2400
  3520.       case B2400: ss = 2400L; break;
  3521. #endif /* B2400 */
  3522.  
  3523. #ifdef B4800
  3524.       case B4800: ss = 4800L; break;
  3525. #endif /* B4800 */
  3526.  
  3527. #ifdef B9600
  3528.       case B9600: ss = 9600L; break;
  3529. #endif /* B9600 */
  3530.  
  3531. #ifdef B19200
  3532.       case B19200: ss = 19200L; break;
  3533. #else
  3534. #ifdef EXTA
  3535.       case EXTA: ss = 19200L; break;
  3536. #endif /* EXTA */
  3537. #endif /* B19200 */
  3538.  
  3539. #ifndef MINIX
  3540. #ifdef B38400
  3541.       case B38400: ss = 38400L; break;
  3542. #else
  3543. #ifdef EXTB
  3544.       case EXTB: ss = 38400L; break;
  3545. #endif /* EXTB */
  3546. #endif /* B38400 */
  3547. #endif /* MINIX */
  3548.  
  3549. #ifdef HPUX
  3550. #ifdef _B57600
  3551.       case _B57600: ss = 57600L; break;
  3552. #endif /* _B57600 */
  3553. #ifdef _B115200
  3554.       case _B115200: ss = 115200L; break;
  3555. #endif /* _B115200 */
  3556. #endif /* HPUX */
  3557.  
  3558.       default:
  3559.     ss = -1; break;
  3560.     }
  3561.     sprintf(temp,"%ld",ss);
  3562.     debug(F110,"speed",temp,0);
  3563.     return(ss);
  3564. }
  3565.  
  3566. /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
  3567.  
  3568. #ifdef COHERENT
  3569. #ifdef FIONREAD
  3570. #undef FIONREAD
  3571. #endif
  3572. #define FIONREAD TIOCQUERY
  3573. #define PEEKTYPE int
  3574. #else
  3575. #define PEEKTYPE long
  3576. #endif /* COHERENT */
  3577.  
  3578. #ifdef MYREAD
  3579.  
  3580. /* Private buffer for myread() and its companions.  Not for use by anything
  3581.  * else.  ttflui() is allowed to reset them to initial values.  ttchk() is
  3582.  * allowed to read my_count.
  3583.  *
  3584.  * my_item is an index into mybuf[].  Increment it *before* reading mybuf[].
  3585.  *
  3586.  * A global parity mask variable could be useful too.  We could use it to
  3587.  * let myread() strip the parity on its own, instead of stripping sign
  3588.  * bits as it does now.
  3589.  */
  3590. #define MYBUFLEN 256
  3591. #ifdef SUNX25
  3592. /*
  3593.   On X.25 connections, there is an extra control byte at the beginning.
  3594. */
  3595. static CHAR x25buf[MYBUFLEN+1];        /* Communication device input buffer */
  3596. static CHAR  *mybuf = x25buf+1;
  3597. #else
  3598. static CHAR mybuf[MYBUFLEN];
  3599. #endif /* SUNX25 */
  3600.  
  3601. static int my_count = 0;        /* Number of chars still in mybuf */
  3602. static int my_item = -1;        /* Last index read from mybuf[] */
  3603.  
  3604. /* myread() -- Efficient read of one character from communications line.
  3605.  *
  3606.  * Uses a private buffer to minimize the number of expensive read() system
  3607.  * calls.  Essentially performs the equivalent of read() of 1 character, which
  3608.  * is then returned.  By reading all available input from the system buffers
  3609.  * to the private buffer in one chunk, and then working from this buffer, the
  3610.  * number of system calls is reduced in any case where more than one character
  3611.  * arrives during the processing of the previous chunk, for instance high
  3612.  * baud rates or network type connections where input arrives in packets.
  3613.  * If the time needed for a read() system call approaches the time for more
  3614.  * than one character to arrive, then this mechanism automatically compensates
  3615.  * for that by performing bigger read()s less frequently.  If the system load
  3616.  * is high, the same mechanism compensates for that too.
  3617.  *
  3618.  * myread() is a macro that returns the next character from the buffer.  If the
  3619.  * buffer is empty, mygetbuf() is called.  See mygetbuf() for possible error
  3620.  * returns.
  3621.  *
  3622.  * This should be efficient enough for any one-character-at-a-time loops.
  3623.  * For even better efficiency you might use memcpy()/bcopy() or such between
  3624.  * buffers (since they are often better optimized for copying), but it may not
  3625.  * be worth it if you have to take an extra pass over the buffer to strip
  3626.  * parity and check for CTRL-C anyway.
  3627.  *
  3628.  * Note that if you have been using myread() from another program module, you
  3629.  * may have some trouble accessing this macro version and the private variables
  3630.  * it uses.  In that case, just add a function in this module, that invokes the
  3631.  * macro.
  3632.  */
  3633. #define myread()  (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
  3634.  
  3635. /* Specification: Push back up to one character onto myread()'s queue.
  3636.  *
  3637.  * This implementation: Push back characters into mybuf. At least one character
  3638.  * must have been read through myread() before myunrd() may be used.  After
  3639.  * EOF or read error, again, myunrd() can not be used.  Sometimes more than
  3640.  * one character can be pushed back, but only one character is guaranteed.
  3641.  * Since a previous myread() must have read its character out of mybuf[],
  3642.  * that guarantees that there is space for at least one character.  If push
  3643.  * back was really needed after EOF, a small addition could provide that.
  3644.  *
  3645.  * myunrd() is currently not called from anywhere inside kermit...
  3646.  */
  3647. #ifdef NOTUSED
  3648. myunrd(ch) CHAR ch; {
  3649.     if (my_item >= 0) {
  3650.     mybuf[my_item--] = ch;
  3651.     ++my_count;
  3652.     }
  3653. }
  3654. #endif
  3655.  
  3656. /* mygetbuf() -- Fill buffer for myread() and return first character.
  3657.  *
  3658.  * This function is what myread() uses when it can't get the next character
  3659.  * directly from its buffer.  First, it calls a system dependent myfillbuf()
  3660.  * to read at least one new character into the buffer, and then it returns
  3661.  * the first character just as myread() would have done.  This function also
  3662.  * is responsible for all error conditions that myread() can indicate.
  3663.  *
  3664.  * Returns: When OK    => a positive character, 0 or greater.
  3665.  *        When EOF    => -2.
  3666.  *        When error    => -3, error code in errno.
  3667.  *
  3668.  * Older myread()s additionally returned -1 to indicate that there was nothing
  3669.  * to read, upon which the caller would call myread() again until it got
  3670.  * something.  The new myread()/mygetbuf() always gets something.  If it 
  3671.  * doesn't, then make it do so!  Any program that actually depends on the old
  3672.  * behaviour will break.
  3673.  *
  3674.  * The older version also used to return -2 both for EOF and other errors,
  3675.  * and used to set errno to 9999 on EOF.  The errno stuff is gone, EOF and
  3676.  * other errors now return different results, although Kermit currently never
  3677.  * checks to see which it was.  It just disconnects in both cases.
  3678.  *
  3679.  * Kermit lets the user use the quit key to perform some special commands
  3680.  * during file transfer.  This causes read(), and thus also mygetbuf(), to
  3681.  * finish without reading anything and return the EINTR error.  This should
  3682.  * be checked by the caller.  Mygetbuf() could retry the read() on EINTR,
  3683.  * but if there is nothing to read, this could delay Kermit's reaction to
  3684.  * the command, and make Kermit appear unresponsive.
  3685.  *
  3686.  * The debug() call should be removed for optimum performance.
  3687.  */
  3688. int
  3689. mygetbuf() {
  3690.     my_count = myfillbuf();
  3691.     debug(F101, "myfillbuf read", "", my_count);
  3692.     if (my_count <= 0)
  3693.       return(my_count < 0 ? -3 : -2);
  3694.     --my_count;
  3695.     return(255 & (int)mybuf[my_item = 0]);
  3696. }
  3697.  
  3698. /* myfillbuf():
  3699.  * System-dependent read() into mybuf[], as many characters as possible.
  3700.  *
  3701.  * Returns: OK => number of characters read, always more than zero.
  3702.  *          EOF => 0
  3703.  *          Error => -1, error code in errno.
  3704.  *
  3705.  * If there is input available in the system's buffers, all of it should be
  3706.  * read into mybuf[] and the function return immediately.  If no input is
  3707.  * available, it should wait for a character to arrive, and return with that
  3708.  * one in mybuf[] as soon as possible.  It may wait somewhat past the first
  3709.  * character, but be aware that any such delay lengthens the packet turnaround
  3710.  * time during kermit file transfers.  Should never return with zero characters
  3711.  * unless EOF or irrecoverable read error.
  3712.  *
  3713.  * Correct functioning depends on the correct tty parameters being used.
  3714.  * Better control of current parameters is required than may have been the
  3715.  * case in older Kermit releases.  For instance, O_NDELAY (or equivalent) can 
  3716.  * no longer be sometimes off and sometimes on like it used to, unless a 
  3717.  * special myfillbuf() is written to handle that.  Otherwise the ordinary 
  3718.  * myfillbuf()s may think they have come to EOF.
  3719.  *
  3720.  * If your system has a facility to directly perform the functioning of
  3721.  * myfillbuf(), then use it.  If the system can tell you how many characters
  3722.  * are available in its buffers, then read that amount (but not less than 1).
  3723.  * If the system can return a special indication when you try to read without
  3724.  * anything to read, while allowing you to read all there is when there is
  3725.  * something, you may loop until there is something to read, but probably that
  3726.  * is not good for the system load.
  3727.  */
  3728.  
  3729. #ifdef SVORPOSIX
  3730.     /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
  3731.      * and CLOCAL set any way you like.  This way, read() will do exactly
  3732.      * what is required by myfillbuf(): If there is data in the buffers
  3733.      * of the O.S., all available data is read into mybuf, up to the size
  3734.      * of mybuf.  If there is none, the first character to arrive is
  3735.      * awaited and returned.
  3736.      */
  3737. int
  3738. myfillbuf() {
  3739. #ifdef sxaE50
  3740.     /* From S. Dezawa at Fujifilm in Japan.  I don't know why this is */
  3741.     /* necessary for the sxa E50, but it is. */
  3742.     return read(ttyfd, mybuf, 255);
  3743. #else
  3744.     /* sizeof(mybuf) should be MYBUFL == 256 */
  3745.     return read(ttyfd, mybuf, sizeof(mybuf));
  3746. #endif /* sxaE50 */
  3747. }
  3748.  
  3749. #else /* not AT&T or POSIX */
  3750.  
  3751. #ifdef aegis
  3752.     /* This is quoted from the old myread().  The semantics seem to be
  3753.      * alright, but maybe errno would not need to be set even when
  3754.      * there is no error?  I don't know aegis.
  3755.      */
  3756. int
  3757. myfillbuf() {
  3758.     int count;
  3759.  
  3760.     count = ios_$get((short)ttyfd, ios_$cond_opt, mybuf, 256L, st);
  3761.     errno = EIO;
  3762.     if (st.all == ios_$get_conditional_failed) /* get at least one */
  3763.       count = ios_$get((short)ttyfd, 0, mybuf, 1L, st);
  3764.     if (st.all == ios_$end_of_file)
  3765.       return(0);
  3766.     else if (st.all != status_$ok) {
  3767.     errno = EIO;
  3768.     return(-1);
  3769.     }
  3770.     return(count);
  3771. }
  3772. #else /* !aegis */
  3773.  
  3774. #ifdef FIONREAD
  3775.     /* This is for systems with FIONREAD.  FIONREAD returns the number
  3776.      * of characters available for reading. If none are available, wait
  3777.      * until something arrives, otherwise return all there is.
  3778.      */
  3779. int
  3780. myfillbuf() {
  3781.     PEEKTYPE avail;
  3782.     int x;
  3783.  
  3784. #ifdef SUNX25
  3785. /*
  3786.   SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
  3787.   Depends on SunOS having FIONREAD, not because we use it, but just so this
  3788.   code is grouped correctly within the #ifdefs.  Let's hope Solaris keeps it.
  3789.  
  3790.   We call x25xin() instead of read() so that Q-Bit packets, which contain
  3791.   X.25 service-level information (e.g. PAD parameter changes), can be processed
  3792.   transparently to the upper-level code.  This is a blocking read, and so
  3793.   we depend on higher-level code (such as ttinc()) to set any necessary alarms.
  3794. */    
  3795.     extern int nettype;
  3796.     if (netconn && nettype == NET_SX25) {
  3797.     while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
  3798.     return(x - 1);            /* "-1" compensates for extra status byte */
  3799.     }    
  3800. #endif /* SUNX25 */
  3801.  
  3802.     x = ioctl(ttyfd, FIONREAD, &avail);
  3803.     if (x < 0) {
  3804.     debug(F101,"myfillbuf FIONREAD","",x);
  3805.     debug(F101,"myfillbuf errno","",errno);
  3806.     }
  3807.     if (x < 0 || avail == 0)
  3808.       avail = 1;
  3809.  
  3810.     if (avail > MYBUFLEN)
  3811.       avail = MYBUFLEN;
  3812.  
  3813.     return(read(ttyfd, mybuf, (int) avail));
  3814. }
  3815.  
  3816. #else /* !FIONREAD */
  3817. /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
  3818. /* When there is no other possibility, read 1 character at a time. */
  3819. int
  3820. myfillbuf() {
  3821.     return read(ttyfd, mybuf, 1);
  3822. }
  3823.  
  3824. #endif /* !FIONREAD */
  3825. #endif /* !aegis */
  3826. #endif /* !ATTSV */
  3827.  
  3828. #endif /* MYREAD */
  3829.  
  3830. /*  T T F L U I  --  Flush tty input buffer */
  3831.  
  3832. int
  3833. ttflui() {
  3834. #ifdef BSD44
  3835.     int n;
  3836. #endif /* BSD44 */
  3837. #ifndef SVORPOSIX
  3838.     int n;
  3839. #endif /* SVORPOSIX */
  3840.  
  3841. #ifdef MYREAD
  3842. /*
  3843.   Flush internal MYREAD buffer *FIRST*, in all cases.
  3844. */
  3845.     my_count = 0;            /* Reset count to zero */
  3846.     my_item = -1;            /* And buffer index to -1 */
  3847. #endif /* MYREAD */
  3848.  
  3849. #ifdef NETCONN
  3850. /*
  3851.   Network flush is done specially, in the network support module.
  3852. */
  3853.     if (netconn) return(netflui());
  3854. #endif /* NETCONN */
  3855.  
  3856.     debug(F101,"ttflui ttyfd","",ttyfd);
  3857.     if (ttyfd < 0) return(-1);
  3858.  
  3859. #ifdef aegis
  3860.     sio_$control((short)ttyfd, sio_$flush_in, true, st);
  3861.     if (st.all != status_$ok) {
  3862.     fprintf(stderr, "flush failed: "); error_$print(st);
  3863.     } else {      /* sometimes the flush doesn't work */
  3864.         for (;;) {
  3865.         char buf[256];
  3866.             /* eat all the characters that shouldn't be available */
  3867.             ios_$get((short)ttyfd, ios_$cond_opt, buf, 256L, st); /* (void) */
  3868.             if (st.all == ios_$get_conditional_failed) break;
  3869.             fprintf(stderr, "flush failed(2): "); error_$print(st);
  3870.         }
  3871.     }
  3872. #else
  3873. #ifdef BSD44                /* 4.4 BSD */
  3874.     n = FREAD;                          /* Specify read queue */
  3875.     debug(F101,"ttflui BSD44 flush","",ttyfd);
  3876.     ioctl(ttyfd,TIOCFLUSH,&n);
  3877.     ioctl(ttyfd,TCSAFLUSH,&n);
  3878. #else
  3879. #ifdef POSIX                /* POSIX */
  3880.     tcflush(ttyfd,TCIFLUSH);
  3881. #else
  3882. #ifdef ATTSV                /* System V */
  3883. #ifndef VXVE
  3884.     ioctl(ttyfd,TCFLSH,0);
  3885. #endif /* VXVE */
  3886. #else                    /* Not BSD44, POSIX, or Sys V */
  3887. #ifdef TIOCFLUSH            /* Those with TIOCFLUSH defined */
  3888. #ifdef ANYBSD                /* Berkeley */
  3889.     n = FREAD;                          /* Specify read queue */
  3890.     debug(F101,"ttflui anybsd flush","",ttyfd);
  3891.     ioctl(ttyfd,TIOCFLUSH,&n);
  3892. #else                    /* Others (V7, etc) */
  3893.     ioctl(ttyfd,TIOCFLUSH,0);
  3894. #endif /* ANYBSD */
  3895. #else                    /* All others... */
  3896. /*
  3897.   No system call (that we know about) for input buffer flushing.
  3898.   So see how many there are and read them in a loop, using ttinc().
  3899.   ttinc() is buffered, so we're not getting charged with a system call 
  3900.   per character, just a function call.
  3901. */
  3902.     if ((n = ttchk()) > 0) {
  3903.     debug(F101,"ttflui reading","",n);
  3904.     while ((n--) && ttinc(0) > 1) ;
  3905.     }
  3906. #endif /* TIOCFLUSH */
  3907. #endif /* ATTSV */
  3908. #endif /* POSIX */
  3909. #endif /* BSD44 */
  3910. #endif /* aegis */
  3911.     return(0);
  3912. }
  3913.  
  3914. int
  3915. ttfluo() {                /* Flush output buffer */
  3916. #ifdef POSIX
  3917.     return(tcflush(ttyfd,TCOFLUSH));
  3918. #else
  3919. #ifdef OXOS
  3920.     return(ioctl(ttyfd,TCFLSH,1));
  3921. #else
  3922.     return(0);                /* All others, nothing */
  3923. #endif /* OXOS */
  3924. #endif /* POSIX */
  3925.  
  3926. }
  3927.  
  3928. /* Interrupt Functions */
  3929.  
  3930. /* Set up terminal interrupts on console terminal */
  3931.  
  3932. #ifndef OXOS
  3933. #ifdef SVORPOSIX
  3934. SIGTYP
  3935. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  3936.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  3937.     conesc = 1;
  3938.     debug(F101,"esctrp caught SIGQUIT","",conesc);
  3939. }
  3940. #endif /* SVORPOSIX */
  3941. #endif /* OXOS */
  3942.  
  3943. #ifdef V7
  3944. SIGTYP
  3945. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  3946.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  3947.     conesc = 1;
  3948.     debug(F101,"esctrp caught SIGQUIT","",conesc);
  3949. }
  3950. #endif
  3951.  
  3952. #ifdef C70
  3953. SIGTYP
  3954. esctrp(foo) int foo; {            /* trap console escapes (^\) */
  3955.     conesc = 1;
  3956.     signal(SIGQUIT,SIG_IGN);            /* ignore until trapped */
  3957. }
  3958. #endif
  3959.  
  3960. /*  C O N B G T  --  Background Test  */
  3961.  
  3962. static int jc = 0;            /* 0 = no job control */
  3963.  
  3964. /*
  3965.   Call with flag == 1 to prevent signal test, which can not be expected
  3966.   to work during file transfer, when SIGINT probably *is* set to SIG_IGN.  
  3967.  
  3968.   Call with flag == 0 to use the signal test, but only if the process-group
  3969.   test fails, as it does on some UNIX systems, where getpgrp() is buggy,
  3970.   requires an argument when the man page says it doesn't, or vice versa.
  3971.  
  3972.   If flag == 0 and the process-group test fails, then we determine background
  3973.   status simply (but not necessarily reliably) from isatty().
  3974.  
  3975.   conbgt() sets the global backgrd = 1 if we appear to be in the background,
  3976.   and to 0 if we seem to be in the foreground.  conbgt() is highly prone to
  3977.   misbehavior.
  3978. */
  3979. VOID
  3980. conbgt(flag) int flag; {
  3981.     int x = -1,                /* process group or SIGINT test */
  3982.         y = 0;                /* isatty() test */
  3983. /*
  3984.   Check for background operation, even if not running on real tty, so that
  3985.   background flag can be set correctly.  If background status is detected,
  3986.   then Kermit will not issue its interactive prompt or most messages.
  3987.   If your prompt goes away, you can blame (and fix?) this function.
  3988. */
  3989.  
  3990. /* Use process-group test if possible. */
  3991.  
  3992. #ifdef POSIX                /* We can do it in POSIX */
  3993. #define PGROUP_T
  3994. #else
  3995. #ifdef BSD4                /* and in BSD 4.x. */
  3996. #define PGROUP_T
  3997. #else
  3998. #ifdef HPUXJOBCTL            /* and in most HP-UX's */
  3999. #define PGROUP_T
  4000. #else
  4001. #ifdef TIOCGPGRP            /* and anyplace that has this ioctl. */
  4002. #define PGROUP_T
  4003. #endif /* TIOCGPGRP */
  4004. #endif /* HPUXJOBCTL */
  4005. #endif /* BSD4 */
  4006. #endif /* POSIX */
  4007.  
  4008. #ifdef MIPS                /* Except if it doesn't work... */
  4009. #undef PGROUP_T
  4010. #endif /* MIPS */
  4011.  
  4012. #ifdef PGROUP_T
  4013. /*
  4014.   Semi-reliable process-group test.  Check whether this process's group is
  4015.   the same as the controlling terminal's process group.  This works if the
  4016.   getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
  4017. */
  4018.     PID_T mypgrp = (PID_T)0;        /* Kermit's process group */
  4019.     PID_T ctpgrp = (PID_T)0;        /* The terminal's process group */
  4020. #ifndef _POSIX_SOURCE
  4021. /*
  4022.   The getpgrp() prototype is obtained from system header files for POSIX 
  4023.   and Sys V R4 compilations.  Other systems, who knows.  Some complain about
  4024.   a duplicate declaration here, others don't, so it's safer to leave it in
  4025.   if we don't know for certain.
  4026. */
  4027. #ifndef SVR4
  4028. #ifndef PS2AIX10
  4029.     extern PID_T getpgrp();
  4030. #endif /* PS2AIX10 */
  4031. #endif /* SVR4 */
  4032. #endif /* _POSIX_SOURCE */
  4033.  
  4034. /* Get my process group. */
  4035.  
  4036. #ifdef SVR3 /* Maybe this should be ATTSV? */
  4037. /* This function is not described in SVID R2 */
  4038.     mypgrp = getpgrp();
  4039.     debug(F101,"ATTSV conbgt process group","",(int) mypgrp);
  4040. #else
  4041. #ifdef POSIX
  4042.     mypgrp = getpgrp();
  4043.     debug(F101,"POSIX conbgt process group","",(int) mypgrp);
  4044. #else
  4045. #ifdef OSFPC
  4046.     mypgrp = getpgrp();
  4047.     debug(F101,"OSF conbgt process group","",(int) mypgrp);
  4048. #else
  4049. #ifdef QNX
  4050.     mypgrp = getpgrp();
  4051.     debug(F101,"QNX conbgt process group","",(int) mypgrp);
  4052. #else /* BSD, V7, etc */
  4053.     mypgrp = getpgrp(0);
  4054.     debug(F101,"BSD conbgt process group","",(int) mypgrp);
  4055. #endif /* QNX */
  4056. #endif /* OSFPC */
  4057. #endif /* POSIX */
  4058. #endif /* SVR3 */
  4059.  
  4060. /* Now get controlling tty's process group */
  4061. #ifdef BSD44ORPOSIX
  4062.     ctpgrp = tcgetpgrp(1);        /* The POSIX way */
  4063.     debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp);
  4064. #else
  4065.     ioctl(1, TIOCGPGRP, &ctpgrp);    /* Or the BSD way */
  4066.     debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp);
  4067. #endif /* BSD44ORPOSIX */
  4068.  
  4069.     if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
  4070.       x = (mypgrp == ctpgrp) ? 0 : 1;    /* If they differ, then background. */
  4071.     else x = -1;            /* If error, remember. */
  4072.     debug(F101,"conbgt process group test","",x);
  4073. #endif /* PGROUP_T */
  4074.  
  4075. /* Try to see if job control is available */
  4076.  
  4077. #ifdef NOJC                /* User override */
  4078.     jc = 0;                /* No job control allowed */
  4079.     debug(F111,"NOJC","jc",jc);
  4080. #else
  4081. #ifdef BSD44
  4082.     jc = 1;
  4083. #else
  4084. #ifdef SVR4ORPOSIX            /* POSIX actually tells us */
  4085.     debug(F100,"SVR4ORPOSIX jc test...","",0);
  4086. #ifdef _SC_JOB_CONTROL
  4087. #ifdef bsdi
  4088.     jc = 1;
  4089. #else
  4090. #ifdef __386BSD__
  4091.     jc = 1;
  4092. #else
  4093.     jc = sysconf(_SC_JOB_CONTROL);    /* Whatever system says */
  4094.     debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
  4095. #endif /* __386BSD__ */
  4096. #endif /* bsdi */
  4097. #else
  4098. #ifdef _POSIX_JOB_CONTROL
  4099.     jc = 1;                /* By definition */
  4100.     debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
  4101. #else
  4102.     jc = 0;                /* Assume job control not allowed */
  4103.     debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
  4104. #endif /* _POSIX_JOB_CONTROL */
  4105. #endif /* _SC_JOB_CONTROL */
  4106. #else
  4107. #ifdef BSD4
  4108.     jc = 1;                /* Job control allowed */
  4109.     debug(F111,"BSD job control","jc",jc);
  4110. #else
  4111. #ifdef SVR3JC
  4112.     jc = 1;                /* JC allowed */
  4113.     debug(F111,"SVR3 job control","jc",jc);
  4114. #else
  4115. #ifdef OXOS
  4116.     jc = 1;                /* JC allowed */
  4117.     debug(F111,"X/OS job control","jc",jc);
  4118. #else
  4119.     jc = 0;                /* JC not allowed */
  4120.     debug(F111,"job control catch-all","jc",jc);
  4121. #endif /* OXOS */
  4122. #endif /* SVR3JC */
  4123. #endif /* BSD4 */
  4124. #endif /* SVR4ORPOSIX */
  4125. #endif /* BSD44 */
  4126. #endif /* NOJC */
  4127.     debug(F101,"conbgt jc","",jc);
  4128.  
  4129. /*
  4130.   Another background test.
  4131.   Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
  4132.   which is done by the shell (sh) if the program is started with '&'.
  4133.   Unfortunately, this is NOT done by csh or ksh so watch out!
  4134.   Note, it's safe to set SIGINT to SIG_IGN here, because further down
  4135.   we always set it to something else.
  4136. */
  4137.     if (x < 0 && !flag) {        /* Didn't get good results above... */
  4138.  
  4139.     SIGTYP (*osigint)();
  4140.  
  4141.     osigint = signal(SIGINT,SIG_IGN);    /* What is SIGINT set to? */
  4142.     x = (osigint == SIG_IGN) ? 1 : 0;    /* SIG_IGN? */
  4143.     debug(F101,"conbgt osigint","",(int) osigint);
  4144.     debug(F101,"conbgt signal test","",x);
  4145.     }
  4146.  
  4147. /* Also check to see if we're running with redirected stdio. */
  4148. /* This is not really background operation, but we want to act as though */
  4149. /* it were. */
  4150.  
  4151.     y = (isatty(0) && isatty(1)) ? 1 : 0;
  4152.     debug(F101,"conbgt isatty test","",y);
  4153.  
  4154. #ifdef BSD29
  4155. /* The process group and/or signal test doesn't work under these... */
  4156.     backgrd = !y;
  4157. #else
  4158. #ifdef sxaE50
  4159.     backgrd = !y;
  4160. #else
  4161. #ifdef MINIX
  4162.     backgrd = !y;
  4163. #else
  4164.     if (x > -1)
  4165.       backgrd = (x || !y) ? 1 : 0;
  4166.     else backgrd = !y;
  4167. #endif /* BSD29 */
  4168. #endif /* sxaE50 */
  4169. #endif /* MINIX */
  4170.     debug(F101,"conbgt backgrd","",backgrd);
  4171. }
  4172.  
  4173. /*  C O N I N T  --  Console Interrupt setter  */
  4174.  
  4175. /*
  4176.   First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
  4177.   Second arg is pointer to function to handle SIGTSTP (suspend).
  4178. */
  4179.  
  4180. VOID                    /* Set terminal interrupt traps. */
  4181. #ifdef CK_ANSIC
  4182. #ifdef apollo
  4183. conint(f,s) SIGTYP (*f)(), (*s)();
  4184. #else
  4185. conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
  4186. #endif /* apollo */
  4187. #else
  4188. conint(f,s) SIGTYP (*f)(), (*s)();
  4189. #endif /* CK_ANSIC */
  4190. /* conint */ {
  4191.  
  4192.     conbgt(0);                /* Do background test. */
  4193.  
  4194. /* Set the desired handlers for hangup and software termination. */
  4195.  
  4196.     signal(SIGTERM,f);                  /* Software termination */
  4197.  
  4198. #ifdef COMMENT
  4199. /*
  4200.   Prior to edit 184, we used to trap SIGHUP here.  That is clearly wrong;
  4201.   on some systems, it would leave the user's process on the terminal after
  4202.   the phone hung up.  But the trap was here for a reason: most likely some
  4203.   UNIX systems (init, getty, or login) fail to properly restore the terminal
  4204.   modes after regaining control of a hung-up-upon login terminal.  Therefore
  4205.   removing this trap is likely to cause problems too.  A more sensible
  4206.   approach would be to use a special handler for HANGUP, which would restore
  4207.   the terminal modes and then exit().  But that could leave zombie processes
  4208.   around (like the lower CONNECT fork, or any fork started by zxcmd()), but
  4209.   there is probably no clean, portable, reliable way for Kermit to kill all
  4210.   its forks.  So we just exit() and hope that UNIX fixes the terminal modes
  4211.   before the next person tries to log in.
  4212. */
  4213.     signal(SIGHUP,f);                   /* Hangup */
  4214. #endif /* COMMENT */
  4215.  
  4216. /* Now handle keyboard stop, quit, and interrupt signals. */
  4217. /* Check if invoked in background -- if so signals set to be ignored. */
  4218. /* However, if running under a job control shell, don't ignore them. */
  4219. /* We won't be getting any, as we aren't in the terminal's process group. */
  4220.  
  4221.     debug(F101,"conint backgrd","",backgrd);
  4222.     debug(F101,"conint jc","",jc);
  4223.  
  4224.     if (backgrd && !jc) {        /* In background, ignore signals */
  4225.     debug(F101,"conint background ignoring signals, jc","",jc);
  4226. #ifdef SIGTSTP
  4227.         signal(SIGTSTP,SIG_IGN);        /* Keyboard stop */
  4228. #endif /* SIGTSTP */
  4229.         signal(SIGQUIT,SIG_IGN);        /* Keyboard quit */
  4230.         signal(SIGINT,SIG_IGN);         /* Keyboard interrupt */
  4231.     } else {                /* Else in foreground or suspended */
  4232.     debug(F101,"conint foreground catching signals, jc","",jc);
  4233.         signal(SIGINT,f);               /* Catch terminal interrupt */
  4234.  
  4235. #ifdef SIGTSTP                /* Keyboard stop (suspend) */
  4236.     debug(F101,"conint SIGSTSTP","",(int) s);
  4237.     if (s == NULL) s = SIG_DFL;
  4238. #ifdef NOJC                /* No job control allowed. */
  4239.     signal(SIGTSTP,SIG_IGN);
  4240. #else                    /* Job control allowed */
  4241.     if (jc)                /* if available. */
  4242.       signal(SIGTSTP,s);
  4243.     else
  4244.       signal(SIGTSTP,SIG_IGN);
  4245. #endif /* NOJC */
  4246. #endif /* SIGTSTP */
  4247.  
  4248. #ifndef OXOS
  4249. #ifdef SVORPOSIX
  4250.         signal(SIGQUIT,esctrp);         /* Quit signal, Sys III/V. */
  4251.         if (conesc) conesc = 0;         /* Clear out pending escapes */
  4252. #else
  4253. #ifdef V7
  4254.         signal(SIGQUIT,esctrp);         /* V7 like Sys III/V */
  4255.         if (conesc) conesc = 0;
  4256. #else
  4257. #ifdef aegis
  4258.         signal(SIGQUIT,f);              /* Apollo, catch it like others. */
  4259. #else
  4260.         signal(SIGQUIT,SIG_IGN);        /* Others, ignore like 4D & earlier. */
  4261. #endif /* aegis */
  4262. #endif /* V7 */
  4263. #endif /* SVORPOSIX */
  4264. #endif /* OXOS */
  4265.     }
  4266. }
  4267.  
  4268.  
  4269. /*  C O N N O I  --  Reset console terminal interrupts */
  4270.  
  4271. SIGTYP                    /* Dummy function to ignore signals */
  4272. #ifdef CK_ANSIC
  4273. sig_ign(int foo)
  4274. #else
  4275. sig_ign(foo) int foo;
  4276. #endif /* CK_ANSIC */
  4277. /* sig_IGN */ {                /* Just like the real one, but has  */
  4278. }                    /* different address. */
  4279.  
  4280. VOID
  4281. connoi() {                              /* Console-no-interrupts */
  4282.  
  4283.     debug(F100,"connoi","",0);
  4284. #ifdef SIGTSTP
  4285.     signal(SIGTSTP,SIG_DFL);
  4286. #endif /* SIGTSTP */
  4287.     /* Note the locally defined replacement for SIG_IGN that is used here */
  4288.     /* for the SIGINT setting.  This is done so that the Sys V background */
  4289.     /* test -- (signal(SIGINT,SIG_IGN) == SIG_IGN) -- can work.  If we use */
  4290.     /* the real SIG_IGN here, then conint will always decide that this */ 
  4291.     /* program is running in the background! */
  4292.  
  4293.     signal(SIGINT,sig_ign);        /* <--- note! */
  4294.  
  4295.     signal(SIGHUP,SIG_DFL);
  4296.     signal(SIGQUIT,SIG_IGN);
  4297.     signal(SIGTERM,SIG_IGN);
  4298. }
  4299.  
  4300. /*  I N I T R A W Q  --  Set up to read /dev/kmem for character count.  */
  4301.  
  4302. #ifdef  V7
  4303. /*
  4304.  Used in Version 7 to simulate Berkeley's FIONREAD ioctl call.  This
  4305.  eliminates blocking on a read, because we can read /dev/kmem to get the
  4306.  number of characters available for raw input.  If your system can't
  4307.  or you won't let the world read /dev/kmem then you must figure out a
  4308.  different way to do the counting of characters available, or else replace
  4309.  this by a dummy function that always returns 0.
  4310. */
  4311. /*
  4312.  * Call this routine as: initrawq(tty)
  4313.  * where tty is the file descriptor of a terminal.  It will return
  4314.  * (as a char *) the kernel-mode memory address of the rawq character
  4315.  * count, which may then be read.  It has the side-effect of flushing
  4316.  * input on the terminal.
  4317.  */
  4318. /*
  4319.  * John Mackin, Physiology Dept., University of Sydney (Australia)
  4320.  * ...!decvax!mulga!physiol.su.oz!john
  4321.  *
  4322.  * Permission is hereby granted to do anything with this code, as
  4323.  * long as this comment is retained unmodified and no commercial
  4324.  * advantage is gained.
  4325.  */
  4326. #ifndef MINIX
  4327. #ifndef COHERENT
  4328. #include <a.out.h>
  4329. #include <sys/proc.h>
  4330. #endif /* COHERENT */
  4331. #endif /* MINIX */
  4332.  
  4333. #ifdef COHERENT
  4334. #include <l.out.h>
  4335. #include <sys/proc.h>
  4336. #endif /* COHERENT */
  4337.  
  4338. char *
  4339. initrawq(tty) int tty; {
  4340. #ifdef MINIX
  4341.     return(0);
  4342. #else
  4343. #ifdef UTS24
  4344.     return(0);
  4345. #else
  4346. #ifdef BSD29
  4347.     return(0);
  4348. #else
  4349.     long lseek();
  4350.     static struct nlist nl[] = {
  4351.         {PROCNAME},
  4352.         {NPROCNAME},
  4353.         {""}
  4354.     };
  4355.     static struct proc *pp;
  4356.     char *qaddr, *p, c;
  4357.     int m;
  4358.     PID_T pid, me;
  4359.     NPTYPE xproc;                       /* Its type is defined in makefile. */
  4360.     int catch();
  4361.  
  4362.     me = getpid();
  4363.     if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
  4364.     nlist(BOOTNAME, nl);
  4365.     if (nl[0].n_type == 0) err("proc array");
  4366.  
  4367.     if (nl[1].n_type == 0) err("nproc");
  4368.  
  4369.     lseek(m, (long)(nl[1].n_value), 0);
  4370.     read (m, &xproc, sizeof(xproc));
  4371.     saval = signal(SIGALRM, catch);
  4372.     if ((pid = fork()) == 0) {
  4373.         while(1)
  4374.             read(tty, &c, 1);
  4375.     }
  4376.     alarm(2);
  4377.  
  4378.     if(setjmp(jjbuf) == 0) {
  4379.         while(1)
  4380.       read(tty, &c, 1);
  4381.     }
  4382.     signal(SIGALRM, SIG_DFL);
  4383.  
  4384. #ifdef DIRECT
  4385.     pp = (struct proc *) nl[0].n_value;
  4386. #else
  4387.     if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
  4388.     if (read(m, &pp, sizeof(pp)) != sizeof(pp))  err("no read of proc ptr");
  4389. #endif
  4390.     lseek(m, (long)(nl[1].n_value), 0);
  4391.     read(m, &xproc, sizeof(xproc));
  4392.  
  4393.     if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
  4394.     if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
  4395.     if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
  4396.         err("read proc table");
  4397.     for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
  4398.         if (pp -> p_pid == (short) pid) goto iout;
  4399.     }
  4400.     err("no such proc");
  4401.  
  4402. iout:
  4403.     close(m);
  4404.     qaddr = (char *)(pp -> p_wchan);
  4405.     free (p);
  4406.     kill(pid, SIGKILL);
  4407.     wait((WAIT_T)0);             /* Destroy the ZOMBIEs! */
  4408.     return (qaddr);
  4409. #endif
  4410. #endif
  4411. #endif
  4412. }
  4413.  
  4414. /*  More V7-support functions...  */
  4415.  
  4416. static VOID
  4417. err(s) char *s; {
  4418.     char buf[200];
  4419.  
  4420.     sprintf(buf, "fatal error in initrawq: %s", s);
  4421.     perror(buf);
  4422.     doexit(1,-1);
  4423. }
  4424.  
  4425. static VOID
  4426. catch(foo) int foo; {
  4427.     longjmp(jjbuf, -1);
  4428. }
  4429.  
  4430.  
  4431. /*  G E N B R K  --  Simulate a modem break.  */
  4432.  
  4433. #ifdef MINIX
  4434. #define BSPEED B110
  4435. #else
  4436. #define BSPEED B150
  4437. #endif /* MINIX */
  4438.  
  4439. VOID
  4440. genbrk(fn,msec) int fn, msec; {
  4441.     struct sgttyb ttbuf;
  4442.     int ret, sospeed, x, y;
  4443.  
  4444.     ret = ioctl(fn, TIOCGETP, &ttbuf);
  4445.     sospeed = ttbuf.sg_ospeed;
  4446.     ttbuf.sg_ospeed = BSPEED;
  4447.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  4448.     y = (int)strlen(brnuls);
  4449.     x = ( BSPEED * 100 ) / msec;
  4450.     if (x > y) x = y;
  4451.     ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
  4452.     ttbuf.sg_ospeed = sospeed;
  4453.     ret = ioctl(fn, TIOCSETP, &ttbuf);
  4454.     ret = write(fn, "@", 1);
  4455.     return;
  4456. }
  4457. #endif /* V7 */
  4458.  
  4459. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  4460.  
  4461. /*  Some callers of this want to know whether there is something to read
  4462.  *  either in the system buffers or in our private buffers (and mostly don't
  4463.  *  care how many characters, just whether it's more than zero or not), while
  4464.  *  some others would be better off with the number of characters in our
  4465.  *  private buffers only.
  4466.  *
  4467.  *  Some systems can say how many characters there are in the system buffers.
  4468.  *  Others can not. For those that can't, the number in the private buffers
  4469.  *  will have to do (or should we put the tty into O_NDELAY-mode and try to
  4470.  *  read one character?). If the system can tell whether there is zero or
  4471.  *  more than zero characters, we can return 1 in the latter case even if the
  4472.  *  private buffer is empty. (That is good for sliding windows.)
  4473.  */
  4474. int
  4475. ttchk() {
  4476.     int x;
  4477.     PEEKTYPE n = 0;
  4478.  
  4479. #ifdef COMMENT
  4480. /*
  4481.   This was REALLY slowing TELNET connections down!  Just do the regular
  4482.   ttyfd-based stuff here.  Let the VMS version call nettchk if it has to...
  4483.   FIONREAD definitely works for TELNET, at least on the NeXT and SUNOS.
  4484. */
  4485. #ifdef NETCONN
  4486.     if (netconn) return(nettchk());
  4487. #endif /* NETCONN */
  4488. #endif /* COMMENT */
  4489.  
  4490. #ifdef FIONREAD
  4491.     x = ioctl(ttyfd, FIONREAD, &n);     /* Berkeley and maybe some others */
  4492.     debug(F101,"ttchk FIONREAD return code","",x);
  4493.     debug(F101,"ttchk FIONREAD count","",n);
  4494.     if (x < 0) n = 0;
  4495. #else
  4496. #ifdef  V7
  4497. #ifdef MINIX
  4498.     return(0);
  4499. #else
  4500.     lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
  4501.     x = read(kmem[TTY], &n, sizeof(int));
  4502.     if (x != sizeof(int)) n = 0;
  4503. #endif /* MINIX */
  4504. #else
  4505. #ifdef PROVX1
  4506.     x = ioctl(ttyfd, TIOCQCNT, &ttbuf); /* Pro/3xx Venix V.1 */
  4507.     n = ttbuf.sg_ispeed & 0377;
  4508.     if (x < 0) n = 0;
  4509. #else
  4510. #ifdef RDCHK
  4511. /*
  4512.   Last resort for systems without FIONREAD or equivalent, but with
  4513.   something like rdchk(), like XENIX.
  4514. */
  4515.     if (my_count == 0 && rdchk(ttyfd) > 0) n = 1;
  4516.     debug(F101,"ttchk rdchk","",n);
  4517. #endif /* RDCHK */
  4518. #endif /* PROVX1 */
  4519. #endif /* V7 */
  4520. #endif /* FIONREAD */
  4521.  
  4522. #ifdef MYREAD
  4523. /*
  4524.   For myread() users, add the contents of myread()'s private buffer.
  4525.   Sometimes, this is all there is to construct a result of ttchk() on.
  4526. */
  4527.     if (my_count > 0)
  4528.     n += my_count;
  4529. #endif /* MYREAD */
  4530.  
  4531.     debug(F101,"ttchk returns","",n);
  4532.     return(n);
  4533. }
  4534.  
  4535. /*  T T X I N  --  Get n characters from tty input buffer  */
  4536.  
  4537. /*  Returns number of characters actually gotten, or -1 on failure  */
  4538.  
  4539. /*  Intended for use only when it is known that n characters are actually */
  4540. /*  Available in the input buffer.  */
  4541.  
  4542. int
  4543. ttxin(n,buf) int n; CHAR *buf; {
  4544.     register int x, c;
  4545.   
  4546.     debug(F101,"ttxin n","",n);
  4547.     if (n < 1) return(0);
  4548.     ttpmsk = (ttprty) ? 0177 : 0377;    /* Parity stripping mask. */
  4549.  
  4550. #ifdef SUNX25
  4551.     if (netconn && (ttnet == NET_SX25))    /* X.25 connection */
  4552.       return(x25xin(n,buf));
  4553. #endif /* SUNX25 */
  4554.  
  4555. #ifdef MYREAD
  4556.     debug(F101,"ttxin MYREAD","",0);
  4557.     c = -2;
  4558.     for( x = 0; (x > -1) && (x < n) && (c = myread()) >= 0; )
  4559.       buf[x++] = c & ttpmsk;
  4560.     if (c < 0) {
  4561.     debug(F101,"ttxin myread returns","",c);
  4562.     if (c == -3) x = -1;
  4563.     }
  4564. #else
  4565.     x = read(ttyfd,buf,n);
  4566.     for (c = 0; c < n; c++) buf[c] &= ttpmsk;
  4567.     debug(F101," x","",x);
  4568. #endif /* MYREAD */
  4569.     if (x > 0) buf[x] = '\0';
  4570.     if (x < 0) x = -1;
  4571.     return(x);
  4572. }
  4573.  
  4574. /*  T T O L  --  Write string s, length n, to communication device.  */
  4575. /*
  4576.   Returns:
  4577.    >= 0 on success, number of characters actually written.
  4578.    -1 on failure.
  4579. */
  4580. #define TTOLMAXT 5
  4581. int
  4582. ttol(s,n) int n; CHAR *s; {
  4583.     int x, len, tries;
  4584.  
  4585.     if (ttyfd < 0) return(-1);          /* Not open? */
  4586.     debug(F101,"ttol n","",n);
  4587.     tries = TTOLMAXT;            /* Allow up to this many tries */
  4588.     len = n;                /* Remember original length */
  4589.  
  4590.     while (n > 0 && tries-- > 0) {    /* Be persistent */
  4591.     debug(F101,"ttol try","",TTOLMAXT - tries);
  4592.     x = write(ttyfd,s,n);        /* Write string to device */
  4593.     if (x == n) {            /* Worked? */
  4594.         debug(F101,"ttol ok","",x);    /* OK */
  4595.         return(len);        /* Done */
  4596.     } else if (x < 0) {        /* No, got error? */
  4597.         debug(F101,"ttol failed","",errno);
  4598.         return(-1);
  4599.     } else {            /* No error, so partial success */
  4600.         debug(F101,"ttol partial","",x);
  4601.         s += x;            /* Point to part not written yet */
  4602.         n -= x;            /* Adjust length */
  4603.         if (x > 0) msleep(100);    /* Wait 100 msec */
  4604.     }                /* Go back and try again */
  4605.     }
  4606.     return(n < 1 ? len : -1);        /* Too many tries */
  4607. }
  4608.  
  4609.  
  4610. /*  T T O C  --  Output a character to the communication line  */
  4611.  
  4612. /*
  4613.  This function should only be used for interactive, character-mode operations,
  4614.  like terminal connection, script execution, dialer i/o, where the overhead
  4615.  of the signals and alarms does not create a bottleneck.
  4616. */
  4617. int
  4618. #ifdef CK_ANSIC
  4619. ttoc(char c)
  4620. #else
  4621. ttoc(c) char c;
  4622. #endif /* CK_ANSIC */
  4623. /* ttoc */ {
  4624. #define TTOC_TMO 15            /* Timeout in case we get stuck */
  4625.     int xx;
  4626.     c &= 0xff;
  4627.     /* debug(F101,"ttoc","",(CHAR) c); */
  4628.     if (ttyfd < 0) return(-1);          /* Check for not open. */
  4629.     saval = signal(SIGALRM,timerh);    /* Enable timer interrupt */
  4630.     xx = alarm(TTOC_TMO);        /* for this many seconds. */
  4631.     if (xx < 0) xx = 0;            /* Save old alarm value. */
  4632.     /* debug(F101,"ttoc alarm","",xx); */
  4633.     if (setjmp(sjbuf)) {        /* Timer went off? */
  4634.     ttimoff();            /* Yes, cancel this alarm. */
  4635.     if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
  4636.         /* debug(F100,"ttoc timeout","",0); */
  4637. #ifdef NETCONN
  4638.     if (!netconn) {
  4639. #endif /* NETCONN */
  4640.         debug(F101,"ttoc timeout","",c);
  4641.         if (ttflow == FLO_XONX) {
  4642.         int x = 0, y;
  4643.         debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
  4644. #ifdef POSIX
  4645.         y = tcflow(ttyfd,TCOON); /* POSIX way to unstick. */
  4646.         debug(F100,"ttoc tcflow","",y);
  4647. #else
  4648. #ifdef BSD4                /* Berkeley way to do it. */
  4649. #ifdef TIOCSTART
  4650. /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);".  Who knows? */
  4651.         y = ioctl(ttyfd, TIOCSTART, &x);
  4652.         debug(F101,"ttoc TIOCSTART","",y);
  4653. #endif /* TIOCSTART */
  4654. #endif /* BSD4 */
  4655.                     /* Is there a Sys V way to do this? */
  4656. #endif /* POSIX */
  4657.         }
  4658. #ifdef NETCONN
  4659.         }
  4660. #endif /* NETCONN */
  4661.     return(-1);            /* Return failure code. */
  4662.     } else {
  4663.     if (write(ttyfd,&c,1) < 1) {    /* Try to write the character. */
  4664.         ttimoff();            /* Failed, turn off the alarm. */
  4665.         alarm(xx);            /* Restore previous alarm. */
  4666.         debug(F101,"ttoc error","",errno); /* Log the error, */
  4667.         return(-1);            /* and return the error code. */
  4668.     }
  4669.     }
  4670.     ttimoff();                /* Success, turn off the alarm. */
  4671.     alarm(xx);                /* Restore previous alarm. */
  4672.     return(0);                /* Return good code. */
  4673. }
  4674.  
  4675. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  4676. /*
  4677.   Reads up to "max" characters from the communication line, terminating on:
  4678.  
  4679.     (a) the packet length field if the "turn" argument is zero, or
  4680.     (b) on the packet-end character (eol) if the "turn" argument is nonzero
  4681.     (c) two Ctrl-C's in a row
  4682.  
  4683.   and returns the number of characters read upon success, or if "max" was
  4684.   exceeded or the timeout interval expired before (a) or (b), returns -1.
  4685.  
  4686.   The characters that were input are copied into "dest" with their parity bits
  4687.   stripped if parity was selected.  Returns the number of characters read.
  4688.   Characters after the eol are available upon the next call to this function.
  4689.  
  4690.   The idea is to minimize the number of system calls per packet, and also to
  4691.   minimize timeouts.  This function is the inner loop of the program and must
  4692.   be as efficient as possible.  The current strategy is to use myread().
  4693.  
  4694.   WARNING: this function calls parchk(), which is defined in another module.
  4695.   Normally, ckutio.c does not depend on code from any other module, but there
  4696.   is an exception in this case because all the other ck?tio.c modules also
  4697.   need to call parchk(), so it's better to have it defined in a common place.
  4698.  
  4699.   Since this function has grown to have its fingers so deeply into the 
  4700.   protocol, it is slated for removal: rpack() will take care of everything.
  4701. */
  4702. #ifdef CTRLC
  4703. #undef CTRLC
  4704. #endif /* CTRLC */
  4705. #define CTRLC '\03'
  4706. /*
  4707.   We have four different declarations here because:
  4708.   (a) to allow Kermit to be built without the automatic parity sensing feature
  4709.   (b) one of each type for ANSI C, one for non-ANSI.
  4710. */
  4711. int
  4712. #ifdef PARSENSE
  4713. #ifdef CK_ANSIC
  4714. ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
  4715. #else
  4716. ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
  4717. #endif /* CK_ANSIC */
  4718. #else /* not PARSENSE */
  4719. #ifdef CK_ANSIC
  4720. ttinl(CHAR *dest, int max,int timo, CHAR eol)
  4721. #else
  4722. ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
  4723. #endif /* __SDTC__ */
  4724. #endif /* PARSENSE */
  4725. /* ttinl */ {
  4726.  
  4727. #ifndef MYREAD
  4728.     CHAR ch;
  4729. #endif /* MYREAD */
  4730. #ifdef PARSENSE
  4731.     int pktlen = -1;
  4732.     int lplen = 0;
  4733.     int havelen = 0;
  4734. #endif /* PARSENSE */
  4735.  
  4736.     if (ttyfd < 0) return(-1);          /* Not open. */
  4737.  
  4738.     debug(F101,"ttinl max","",max);
  4739.     debug(F101,"ttinl timo","",timo);
  4740.  
  4741.     *dest = '\0';                       /* Clear destination buffer */
  4742.     if (timo < 0) timo = 0;        /* Safety */
  4743.     if (timo) {                /* Don't time out if timo == 0 */
  4744.     int xx;
  4745.     saval = signal(SIGALRM,timerh);    /* Enable timer interrupt */
  4746.     xx = alarm(timo);        /* Set it. */
  4747.     debug(F101,"ttinl alarm","",xx);
  4748.     }
  4749.     if (setjmp(sjbuf)) {                /* Timer went off? */
  4750.     debug(F100,"ttinl timout","",0); /* Get here on timeout. */
  4751.     /* debug(F110," with",(char *) dest,0); */
  4752.     ttimoff();            /* Turn off timer */
  4753.     return(-1);            /* and return error code. */
  4754.     } else {
  4755.     register int i, m, n;        /* local variables */
  4756.     int ccn = 0;
  4757. #ifdef PARSENSE
  4758.     int flag = 0;
  4759.  
  4760.     debug(F000,"ttinl start","",start);
  4761.     flag = 0;            /* Start of packet flag */
  4762. #endif /* PARSENSE */
  4763.  
  4764.     ttpmsk = m = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */
  4765.  
  4766. #ifdef COMMENT
  4767. /*
  4768.   No longer needed.
  4769. */
  4770. #ifdef SUNX25
  4771.         if (netconn && (ttnet == NET_SX25))
  4772. #ifdef PARSENSE
  4773.       return(x25inl(dest,max,timo,eol,start));
  4774. #else
  4775.       return(x25inl(dest,max,timo,eol));
  4776. #endif /* PARSENSE */
  4777. #endif /* SUNX25 */
  4778. #endif /* COMMENT */
  4779.  
  4780. /* Now read into destination, stripping parity and looking for the */
  4781. /* the packet terminator, and also for two Ctrl-C's typed in a row. */
  4782.  
  4783.     i = 0;                /* Destination index */
  4784.     debug(F101,"ttinl eol","",eol);
  4785.  
  4786. #ifdef MYREAD
  4787.     while (i < max-1) {
  4788.         /* debug(F101,"ttinl i","",i); */
  4789.         if ((n = myread()) < 0) {
  4790.         debug(F101,"ttinl myread failure, n","",n);
  4791.         debug(F101,"ttinl myread errno,","",errno);
  4792.         /* Don't let EINTR break packets. */
  4793.         if (n == -3 && errno == EINTR && i > 0) {
  4794.             debug(F101,"ttinl myread i","",i);
  4795.             continue;
  4796.         }
  4797.         break;
  4798.         }
  4799. #else
  4800.     while ((i < max-1)  &&  (n = read(ttyfd, &ch, 1)) > 0) {
  4801.         n = ch;
  4802. #endif /* MYREAD */
  4803.  
  4804.         /* debug(F101,"ttinl char","", (n & ttpmsk)); */
  4805.  
  4806. #ifdef PARSENSE
  4807. /*
  4808.   Figure out what the length is supposed to be in case the packet
  4809.   has no terminator (as with Honeywell GCOS-8 Kermit).
  4810. */
  4811. #ifndef xunchar
  4812. #define xunchar(ch) (((ch) - 32 ) & 0xFF )    /* Character to number */
  4813. #endif /* xunchar */
  4814.         if ((flag == 0) && ((n & 0x7f) == start)) flag = 1;
  4815.         if (flag) dest[i++] = n & ttpmsk;
  4816. /*
  4817.   If we have not been instructed to wait for a turnaround character, we
  4818.   can go by the packet length field.  If turn != 0, we must wait for the
  4819.   end of line (eol) character before returning.
  4820. */
  4821.         if (i == 2) {
  4822.         pktlen = xunchar(dest[1]);
  4823.         havelen = (pktlen > 1);
  4824.         debug(F101,"ttinl length","",pktlen);
  4825.         } else if (i == 5 && pktlen == 0) {
  4826.         lplen = xunchar(dest[4]);
  4827.         } else if (i == 6 && pktlen == 0) {
  4828.         pktlen = lplen * 95 + xunchar(dest[5]) + 5;
  4829.         havelen = 1;
  4830.         debug(F101,"ttinl length","",pktlen);
  4831.         }
  4832. #else
  4833.         dest[i++] = n & ttpmsk;
  4834. #endif /* PARSENSE */
  4835.         if (xfrcan && ((n & 0x7f) == xfrchr)) { /* Check cancellation */
  4836.         if (++ccn >= xfrnum) {    /* If xfrnum in a row, bail out. */
  4837.             if (timo) {        /* Clear timer. */
  4838.             ttimoff();
  4839.             }
  4840.             fprintf(stderr,"^C...\r\n"); /* Echo Ctrl-C */
  4841.             return(-2);
  4842.         }
  4843.         } else ccn = 0;        /* No cancellation, reset counter, */
  4844.  
  4845. #ifdef PARSENSE
  4846.         if (flag == 0) {
  4847.         debug(F101,"ttinl skipping","",n);
  4848.         continue;
  4849.         }
  4850. #endif /* PARSENSE */
  4851.  
  4852.     /* Check for end of packet */
  4853.  
  4854.         if (
  4855. #ifdef PARSENSE
  4856. /*
  4857.   Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
  4858.   This allows packet terminators and handshake characters to appear
  4859.   literally inside a packet data field.
  4860. */
  4861.         (havelen && (i > pktlen+1) &&
  4862.          (!turn || (turn && (n & 0x7f) == eol)))
  4863. #ifdef COMMENT
  4864.         (!turn && havelen && (i > pktlen+1)) ||
  4865.         (turn && havelen && (i > pktlen+1) && (n & 0x7f) == eol)
  4866. #endif /* COMMENT */
  4867. #else /* !PARSENSE */
  4868. /*
  4869.   Built without PARSENSE, so just look for packet terminator.
  4870. */
  4871.         ((n & 0x7f) == eol)
  4872. #endif /* PARSENSE */
  4873.         ) {
  4874. #ifndef PARSENSE
  4875.         debug(F101,"ttinl got eol","",eol);
  4876.         dest[i] = '\0';        /* Yes, terminate the string, */
  4877.         /* debug(F101,"ttinl i","",i); */
  4878. #else
  4879.         if ((n & 0x7f) != eol) {
  4880.             debug(F101,"ttinl EOP length","",pktlen);
  4881.             debug(F101,"ttinl i","",i);
  4882.         } else debug(F101,"ttinl got eol","",eol);
  4883.         dest[i] = '\0';        /* Terminate the string, */
  4884.         /* Parity checked yet? */
  4885.             if (ttpflg++ == 0 && ttprty == 0) {
  4886.             if ((ttprty = parchk(dest,start,i)) > 0) { /* No, check. */
  4887.             int j;
  4888.             debug(F101,"ttinl senses parity","",ttprty);
  4889.             debug(F110,"ttinl packet before",dest,0);
  4890.             ttpmsk = 0x7f;
  4891.             for (j = 0; j < i; j++)
  4892.               dest[j] &= 0x7f;    /* Strip parity from packet */
  4893.             debug(F110,"ttinl packet after ",dest,0);
  4894.             } else ttprty = 0;    /* restore if parchk error */
  4895.         }
  4896. #endif /* PARSENSE */
  4897.         if (timo) {            /* Turn off timer. */
  4898.             ttimoff();
  4899.         }
  4900.         debug(F111,"ttinl got", dest,i);
  4901.         return(i);
  4902.         }
  4903.     }                /* end of while() */
  4904.     ttimoff();
  4905.     return(-1);
  4906.     }
  4907. }
  4908.  
  4909. /*  T T I N C --  Read a character from the communication line  */
  4910. /*
  4911.  On success, returns the character that was read, >= 0.
  4912.  On failure, returns -1 or other negative myread error code.
  4913. */
  4914. int
  4915. ttinc(timo) int timo; {
  4916.  
  4917.     int n = 0;
  4918. #ifndef MYREAD
  4919.     CHAR ch = 0;
  4920. #endif /* MYREAD */
  4921.  
  4922.     if (ttyfd < 0) return(-1);          /* Not open. */
  4923.     if (timo <= 0) {                    /* Untimed. */
  4924. #ifdef MYREAD
  4925.         /* comm line failure returns -1 thru myread, so no &= 0377 */
  4926.     n = myread();            /* Wait for a character... */
  4927.     /* debug(F101,"ttinc MYREAD n","",n); */
  4928.     return(n < 0 ? n : n & ttpmsk);
  4929. #else
  4930.         while ((n = read(ttyfd,&ch,1)) == 0) /* Wait for a character. */
  4931.         /* Shouldn't have to loop in ver 5A. */
  4932. #ifdef NETCONN      
  4933.       if (netconn) {        /* Special handling for net */
  4934.           netclos();        /* If read() returns 0 it means */
  4935.           netconn = 0;        /* the connection has dropped. */
  4936.           errno = ENOTCONN;
  4937.           return(-2);
  4938.       }
  4939. #endif /* NETCONN */
  4940.       ;
  4941.      /* debug(F000,"ttinc","",ch); */
  4942.         return( (n < 1) ? -3 : (ch & ttpmsk) );
  4943. #endif /* MYREAD */
  4944.     } else {                /* Timed read */
  4945.     int xx;
  4946.     saval = signal(SIGALRM,timerh);    /* Set up handler, save old one. */
  4947.     xx = alarm(timo);        /* Set alarm, save old one. */
  4948.     /* debug(F101,"ttinc alarm","",xx); */
  4949.     if (setjmp(sjbuf)) {        /* Timer expired */
  4950.         n = -1;            /* set flag */
  4951.     } else {
  4952. #ifdef MYREAD
  4953.         n = myread();        /* If managing own buffer... */
  4954.         /* debug(F101,"ttinc myread","",n); */
  4955. #else
  4956.         n = read(ttyfd,&ch,1);    /* Otherwise call the system. */
  4957.         /* debug(F101,"ttinc read","",n); */
  4958.         if (n > 0)
  4959.           n = ch & 255;
  4960.         else
  4961.           n = (n < 0) ? -3 : -2;    /* Special return codes. */
  4962. #endif /* MYREAD */
  4963.     }
  4964.     ttimoff();            /* Turn off the timer */
  4965. /* #ifdef COMMENT */
  4966.     if (n == -1) xx -= timo;    /* and restore any previous alarm */
  4967.     if (xx < 0) xx = 0;        /* adjusted by timeout interval */
  4968.     alarm(xx);            /* if timer expired. */
  4969. /* #endif */ /* COMMENT */
  4970. #ifdef NETCONN
  4971.     if (netconn) {
  4972.         if (n == -2) {        /* read() returns 0 */
  4973.         netclos();        /* on network read failure */
  4974.         netconn = 0;
  4975.         errno = ENOTCONN;
  4976.         }
  4977.     }
  4978. #endif    /* NETCONN */
  4979.     return( (n < 0) ? n : (n & ttpmsk) ); /* Return masked char or neg. */
  4980.     }
  4981. }
  4982.  
  4983. /*  S N D B R K  --  Send a BREAK signal of the given duration  */
  4984.  
  4985. static int
  4986. #ifdef CK_ANSIC
  4987. sndbrk(int msec) {            /* Argument is milliseconds */
  4988. #else
  4989. sndbrk(msec) int msec; {
  4990. #endif /* CK_ANSIC */
  4991. #ifndef POSIX
  4992.     int x, n;
  4993. #endif /* POSIX */
  4994.  
  4995. #ifdef OXOS
  4996. #define BSDBREAK
  4997. #endif /* OXOS */
  4998.  
  4999. #ifdef ANYBSD
  5000. #define BSDBREAK
  5001. #endif /* ANYBSD */
  5002.  
  5003. #ifdef BSD44
  5004. #define BSDBREAK
  5005. #endif /* BSD44 */
  5006.  
  5007. #ifdef COHERENT
  5008. #define BSDBREAK
  5009. #endif /* COHERENT */
  5010.  
  5011. #ifdef PROVX1
  5012.     char spd;
  5013. #endif /* PROVX1 */
  5014.  
  5015.     debug(F101,"ttsndb ttyfd","",ttyfd);
  5016.     if (ttyfd < 0) return(-1);          /* Not open. */
  5017.  
  5018. #ifdef NETCONN
  5019.     if (netconn)             /* Send network BREAK */
  5020.       return(netbreak());
  5021. #endif /* NETCONN */
  5022.  
  5023.     if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
  5024.  
  5025. #ifdef POSIX                /* Easy in POSIX */
  5026.     return(tcsendbreak(ttyfd,msec / 375));
  5027. #else
  5028. #ifdef PROVX1
  5029.     gtty(ttyfd,&ttbuf);                 /* Get current tty flags */
  5030.     spd = ttbuf.sg_ospeed;              /* Save speed */
  5031.     ttbuf.sg_ospeed = B50;              /* Change to 50 baud */
  5032.     stty(ttyfd,&ttbuf);                 /*  ... */
  5033.     n = (int)strlen(brnuls);        /* Send the right number of nulls */
  5034.     x = msec / 91;
  5035.     if (x > n) x = n;
  5036.     write(ttyfd,brnuls,n);
  5037.     ttbuf.sg_ospeed = spd;              /* Restore speed */
  5038.     stty(ttyfd,&ttbuf);                 /*  ... */
  5039.     return(0);
  5040. #else
  5041. #ifdef aegis
  5042.     sio_$control((short)ttyfd, sio_$send_break, msec, st);
  5043.     return(0);
  5044. #else
  5045. #ifdef BSDBREAK
  5046.     n = FWRITE;                         /* Flush output queue. */
  5047. /* Watch out for int vs long problems in &n arg! */
  5048.     ioctl(ttyfd,TIOCFLUSH,&n);          /* Ignore any errors.. */
  5049.     if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) {  /* Turn on BREAK */
  5050.         perror("Can't send BREAK");
  5051.         return(-1);
  5052.     }
  5053.     x = msleep(msec);                    /* Sleep for so many milliseconds */
  5054.     if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) {  /* Turn off BREAK */
  5055.         perror("BREAK stuck!!!");
  5056.         doexit(BAD_EXIT,-1);        /* Get out, closing the line. */
  5057.                                         /*   with bad exit status */
  5058.     }
  5059.     return(x);
  5060. #else
  5061. #ifdef ATTSV
  5062. /*
  5063.   No way to send a long BREAK in Sys V, so send a bunch of regular ones.
  5064.   (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
  5065.   but there's no way for this code to know for sure.)
  5066. */
  5067.     x = msec / 275;
  5068.     for (n = 0; n < x; n++) {
  5069.     if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) {
  5070.         perror("Can't send BREAK");
  5071.         return(-1);
  5072.     }
  5073.     }
  5074.     return(0);
  5075. #else
  5076. #ifdef  V7
  5077.     return(genbrk(ttyfd,250));        /* Simulate a BREAK */
  5078. #endif /* V7 */
  5079. #endif /* BSDBREAK */
  5080. #endif /* ATTSV */
  5081. #endif /* aegis */
  5082. #endif /* PROVX1 */
  5083. #endif /* POSIX */
  5084. }
  5085.  
  5086. /*  T T S N D B  --  Send a BREAK signal  */
  5087.  
  5088. int
  5089. ttsndb() {
  5090.     return(sndbrk(275));
  5091. }
  5092.  
  5093. /*  T T S N D L B  --  Send a Long BREAK signal  */
  5094.  
  5095. int
  5096. ttsndlb() {
  5097.     return(sndbrk(1500));
  5098. }
  5099.  
  5100. /*  M S L E E P  --  Millisecond version of sleep().  */
  5101.  
  5102. /*
  5103.   Call with number of milliseconds (thousandths of seconds) to sleep.
  5104.   Intended only for small intervals.  For big ones, just use sleep().
  5105.   Highly system-dependent.
  5106.   Returns 0 always, even if it didn't work.
  5107. */
  5108.  
  5109. /* Define MSLFTIME for systems that must use an ftime() loop. */
  5110. #ifdef ANYBSD                /* For pre-4.2 BSD versions */
  5111. #ifndef BSD4
  5112. #define MSLFTIME
  5113. #endif /* BSD4 */
  5114. #endif /* ANYBSD */
  5115.  
  5116. #ifdef TOWER1                /* NCR Tower OS 1.0 */
  5117. #define MSLFTIME
  5118. #endif /* TOWER1 */
  5119.  
  5120. #ifdef QNX                /* QNX */
  5121. #define MSLFTIME
  5122. #endif /* QNX */
  5123.  
  5124. #ifdef COHERENT         /* Coherent... */
  5125. #ifndef _I386           /* Maybe Coherent/386 should get this, too */
  5126. #define MSLFTIME        /* Opinions are divided */
  5127. #endif /* _I386 */
  5128. #endif /* COHERENT */
  5129.  
  5130. int
  5131. msleep(m) int m; {
  5132.  
  5133. #ifndef USLEEP
  5134. #ifdef SUNOS4                /* Systems that have usleep() */
  5135. #define USLEEP
  5136. #endif /* SUNOS4 */
  5137. #ifdef SUN4S5
  5138. #define USLEEP
  5139. #endif /* SUN4S5 */
  5140. #ifdef NEXT
  5141. #define USLEEP
  5142. #endif /* NEXT*/
  5143. #endif /* USLEEP */
  5144.  
  5145. #ifdef AIXRS                /* RS/6000 can do select() */
  5146. #define BSD42
  5147. #endif /* AIXRS */
  5148.  
  5149. #ifndef SELECT
  5150. #ifdef BSD44
  5151. #define SELECT
  5152. #endif /* BSD44 */
  5153. #ifdef BSD42
  5154. #define SELECT
  5155. #endif /* BSD42 */
  5156. #ifdef OXOS
  5157. #define SELECT
  5158. #endif /* OXOS */
  5159. #endif /* SELECT */
  5160.  
  5161. #ifdef SELECT
  5162. /* BSD 4.2 & above can do it with select()... */
  5163.     int t1;
  5164.     if (m <= 0) return(0);
  5165.     if (m >= 1000) {            /* Catch big arguments. */
  5166.     sleep(m/1000);
  5167.     m = m % 1000;
  5168.     if (m < 10) return(0);
  5169.     }
  5170.     if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */
  5171.     t1 = tv.tv_sec;                     /* Seconds */
  5172.     tv.tv_sec = 0;                      /* Use select() */
  5173.     tv.tv_usec = m * 1000L;
  5174. #ifdef BSD44
  5175.     select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  5176. #else
  5177. #ifdef BSD43
  5178.     select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
  5179. #else
  5180.     select( 0, (int *)0, (int *)0, (int *)0, &tv );
  5181. #endif /* BSD43 */
  5182. #endif /* BSD44 */
  5183.     return(0);
  5184.  
  5185. #else                    /* Not SELECT */
  5186. #ifdef CK_POLL
  5187.     poll((struct pollfd *) 0, 0, m);
  5188.     return(0);
  5189.  
  5190. #else                    /* Not POLL */
  5191. #ifdef USLEEP
  5192. /*
  5193.   "This routine is implemented using setitimer(2); it requires eight
  5194.   system calls...".  In other words, it might take 5 minutes to sleep
  5195.   for 100 milliseconds...
  5196. */
  5197.     if (m >= 1000) {            /* Catch big arguments. */
  5198.     sleep(m/1000);
  5199.     m = m % 1000;
  5200.     if (m < 10) return(0);
  5201.     }
  5202.     usleep((unsigned int)(m * 1000));
  5203.     return(0);
  5204. #else
  5205. #ifdef aegis
  5206.     time_$clock_t dur;
  5207.  
  5208.     dur.c2.high16 = 0;
  5209.     dur.c2.low32  = 250 * m; /* one millisecond = 250 four microsecond ticks */
  5210.     time_$wait(time_$relative, dur, st);
  5211.     return(0);
  5212. #else
  5213. #ifdef PROVX1
  5214.     if (m <= 0) return(0);
  5215.     sleep(-((m * 60 + 500) / 1000));
  5216.     return(0);
  5217. #else
  5218. #ifdef NAP
  5219.     nap((long)m);
  5220.     return(0);
  5221. #else
  5222. #ifdef ATTSV
  5223. #ifndef BSD44
  5224.     extern long times();        /* Or #include <times.h> ? */
  5225. #endif /* BSD44 */
  5226.     long t1, t2, tarray[4];
  5227.     int t3;
  5228.  
  5229. #ifdef COMMENT
  5230. /* This better be picked up in ckcdeb.h... */
  5231.     char *getenv();
  5232. #endif /* COMMENT */
  5233.     char *cp = getenv("HZ");
  5234.     int CLOCK_TICK;
  5235.     int hertz;
  5236.  
  5237.     if (cp && (hertz = atoi(cp))) {
  5238.         CLOCK_TICK  = 1000 / hertz;
  5239.     } else {                /* probably single user mode */
  5240. #ifdef HZ
  5241.         CLOCK_TICK  = 1000 / HZ;    
  5242. #else
  5243.     static warned = 0;
  5244.     /* HZ always exists in, for instance, SCO Xenix, so you don't have to
  5245.      * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
  5246.      * have Xenix, you have should have nap(), so the best is to use -DNAP
  5247.      * in the makefile. Most systems have HZ.
  5248.      */
  5249.     CLOCK_TICK = 17;        /* 1/60 sec */
  5250.     if (!warned) {
  5251.           printf("warning: environment variable HZ bad... using HZ=%d\r\n",
  5252.          1000 / CLOCK_TICK);
  5253.           warned = 1;
  5254.     }
  5255. #endif /* !HZ */
  5256.     }
  5257.  
  5258.     if (m <= 0) return(0);
  5259.     if (m >= 1000) {            /* Catch big arguments. */
  5260.     sleep(m/1000);
  5261.     m = m % 1000;
  5262.     if (m < 10) return(0);
  5263.     }
  5264.     if ((t1 = times(tarray)) < 0) return(-1);
  5265.     while (1) {
  5266.         if ((t2 = times(tarray)) < 0) return(-1);
  5267.         t3 = ((int)(t2 - t1)) * CLOCK_TICK;
  5268.         if (t3 > m) return(t3);
  5269.     }
  5270. #else /* Not ATTSV */
  5271. #ifdef MSLFTIME                /* Use ftime() loop... */
  5272.     int t1, t3 = 0;
  5273.     if (m <= 0) return(0);
  5274.     if (m >= 1000) {            /* Catch big arguments. */
  5275.     sleep(m/1000);
  5276.     m = m % 1000;
  5277.     if (m < 10) return(0);
  5278.     }
  5279. #ifdef QNX
  5280.     ftime(&ftp);            /* void ftime() in QNX */
  5281. #else
  5282.     if (ftime(&ftp) < 0) return(-1);    /* Get base time. */
  5283. #endif /* QNX */
  5284.     t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
  5285.     while (1) {
  5286.         ftime(&ftp);            /* Get current time and compare. */
  5287.         t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
  5288.         if (t3 > m) return(0);
  5289.     }
  5290. #else
  5291. /* This includes true POSIX, which has no way to do this. */
  5292.     if (m >= 1000) {            /* Catch big arguments. */
  5293.     sleep(m/1000);
  5294.     m = m % 1000;
  5295.     if (m < 10) return(0);
  5296.     }
  5297.     if (m > 0) while (m > 0) m--;    /* Just a dumb busy loop */
  5298.     return(0);
  5299. #endif /* MSLFTIME */
  5300. #endif /* ATTSV */
  5301. #endif /* NAP */
  5302. #endif /* PROVX1 */
  5303. #endif /* aegis */
  5304. #endif /* SELECT */
  5305. #endif /* CK_POLL */
  5306. #endif /* USLEEP */
  5307. }
  5308.  
  5309. /*  R T I M E R --  Reset elapsed time counter  */
  5310.  
  5311. VOID
  5312. rtimer() {
  5313.     tcount = time( (time_t *) 0 );
  5314. }
  5315.  
  5316.  
  5317. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  5318.  
  5319. int
  5320. gtimer() {
  5321.     int x;
  5322.     x = (int) (time( (time_t *) 0 ) - tcount);
  5323.     debug(F101,"gtimer","",x);
  5324.     return( (x < 0) ? 0 : x );
  5325. }
  5326.  
  5327.  
  5328. /*  Z T I M E  --  Return date/time string  */
  5329.  
  5330. VOID
  5331. ztime(s) char **s; {
  5332.  
  5333. #undef ZTIMEV7                /* Which systems need to use */
  5334. #ifdef COHERENT                /* old UNIX Version 7 way... */
  5335. #define ZTIMEV7
  5336. #endif /* COHERENT */
  5337. #ifdef TOWER1
  5338. #define ZTIMEV7
  5339. #endif /* TOWER1 */
  5340. #ifdef ANYBSD
  5341. #ifndef BSD42
  5342. #define ZTIMEV7
  5343. #endif /* BSD42 */
  5344. #endif /* ANYBSD */
  5345. #ifdef V7
  5346. #ifndef MINIX
  5347. #define ZTIMEV7
  5348. #endif /* MINIX */
  5349. #endif /* V7 */
  5350. #ifdef POSIX
  5351. #define ZTIMEV7
  5352. #endif /* POSIX */
  5353.  
  5354. #ifdef ATTSV                /* AT&T way */
  5355. /*  extern long time(); */        /* Theoretically these should */
  5356.     char *ctime();            /* already been dcl'd in <time.h> */
  5357.     long clock_storage;
  5358.     clock_storage = time( (long *) 0 );
  5359.     *s = ctime( &clock_storage );
  5360. #else
  5361. #ifdef PROVX1                /* Venix 1.0 way */
  5362.     int utime[2];
  5363.     time(utime);
  5364.     *s = ctime(utime);
  5365. #else
  5366. #ifdef BSD42                /* 4.2BSD way */
  5367.     char *asctime();
  5368.     struct tm *localtime();
  5369.     struct tm *tp;
  5370.     gettimeofday(&tv, &tz);
  5371.     time(&tv.tv_sec);
  5372.     tp = localtime(&tv.tv_sec);
  5373.     *s = asctime(tp);
  5374. #else
  5375. #ifdef MINIX                /* MINIX way */
  5376. #ifdef COMMENT
  5377.     extern long time();            /* Already got these from <time.h> */
  5378.     extern char *ctime();
  5379. #endif /* COMMENT */
  5380.     time_t utime[2];
  5381.     time(utime);
  5382.     *s = ctime(utime);
  5383. #else
  5384. #ifdef ZTIMEV7                /* The regular way */
  5385.     char *asctime();
  5386.     struct tm *localtime();
  5387.     struct tm *tp;
  5388.     long xclock;
  5389.     time(&xclock);
  5390.     tp = localtime(&xclock);
  5391.     *s = asctime(tp);
  5392. #else                    /* Catch-all for others... */
  5393.     *s = "Ddd Mmm 00 00:00:00 0000\n"    /* Return dummy in asctime() format */
  5394. #endif /* ZTIMEV7 */
  5395. #endif /* MINIX */
  5396. #endif /* BSD42 */
  5397. #endif /* PROVX1 */
  5398. #endif /* SVORPOSIX */
  5399. }
  5400.  
  5401. /*  C O N G M  --  Get console terminal modes.  */
  5402.  
  5403. /*
  5404.   Saves initial console mode, and establishes variables for switching
  5405.   between current (presumably normal) mode and other modes.
  5406.   Should be called when program starts, but only after establishing
  5407.   whether program is in the foreground or background.
  5408.   Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
  5409. */
  5410. int
  5411. congm() {
  5412.     int fd;
  5413.     if (backgrd || !isatty(0)) {    /* If in background. */
  5414.     cgmf = -1;            /* Don't bother, modes are garbage. */
  5415.     return(-1);
  5416.     }
  5417.     if (cgmf > 0) return(0);        /* Already did this. */
  5418.     debug(F100,"congm getting modes","",0); /* Need to do it. */
  5419. #ifdef aegis
  5420.     ios_$inq_type_uid(ios_$stdin, conuid, st);
  5421.     if (st.all != status_$ok) {
  5422.     fprintf(stderr, "problem getting stdin objtype: ");
  5423.     error_$print(st);
  5424.     }
  5425.     concrp = (conuid == mbx_$uid);
  5426.     conbufn = 0;
  5427. #endif /* aegis */
  5428.  
  5429.     if ((fd = open(CTTNAM,2)) < 0) {    /* Open controlling terminal */
  5430.     fprintf(stderr,"Error opening %s\n", CTTNAM);
  5431.     perror("congm");
  5432.     return(-1);
  5433.     }
  5434. #ifdef BSD44ORPOSIX
  5435.     if (tcgetattr(fd,&ccold) < 0) return(-1);
  5436.     if (tcgetattr(fd,&cccbrk) < 0) return(-1);
  5437.     if (tcgetattr(fd,&ccraw) < 0) return(-1);
  5438. #else
  5439. #ifdef ATTSV
  5440.     if (ioctl(fd,TCGETA,&ccold)  < 0) return(-1);
  5441.     if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
  5442.     if (ioctl(fd,TCGETA,&ccraw)  < 0) return(-1);
  5443. #ifdef VXVE
  5444.     cccbrk.c_line = 0;            /* STTY line 0 for CDC VX/VE */
  5445.     if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
  5446.     ccraw.c_line = 0;            /* STTY line 0 for CDC VX/VE */
  5447.     if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
  5448. #endif /* VXVE */
  5449. #else
  5450.     if (gtty(fd,&ccold) < 0) return(-1);
  5451.     if (gtty(fd,&cccbrk) < 0) return(-1);
  5452.     if (gtty(fd,&ccraw) < 0) return(-1);
  5453. #endif /* ATTSV */
  5454. #endif /* BSD44ORPOSIX */
  5455. #ifdef sony_news            /* Sony NEWS */
  5456.     if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
  5457.     perror("congm error getting Kanji mode");
  5458.     debug(F101,"congm error getting Kanji mode","",0);
  5459.     km_con = -1;            /* Make sure this stays undefined. */
  5460.     return(-1);
  5461.     }
  5462. #endif /* sony_news */
  5463.     close(fd);
  5464.     cgmf = 1;                /* Flag that we got them. */
  5465.     return(1);
  5466. }
  5467.  
  5468.  
  5469. /*  C O N C B --  Put console in cbreak mode.  */
  5470.  
  5471. /*  Returns 0 if ok, -1 if not  */
  5472.  
  5473. int
  5474. #ifdef CK_ANSIC
  5475. concb(char esc)
  5476. #else
  5477. concb(esc) char esc;
  5478. #endif /* CK_ANSIC */
  5479. /* concb */ {
  5480.     int x;
  5481.     if (cgmf < 1) return(0);        /* Console modes not available yet */
  5482.     if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
  5483.       return(0);
  5484.     debug(F101,"concb backgrd","",backgrd);
  5485.     if (!isatty(0)) return(0);          /* Only for real ttys */
  5486.     debug(F100,"concb isatty","",0);
  5487.     if (backgrd) return(0);        /* Do nothing if in background. */
  5488.     escchr = esc;                       /* Make this available to other fns */
  5489.     ckxech = 1;                         /* Program can echo characters */
  5490. #ifdef aegis
  5491.     conbufn = 0;
  5492.     if (concrp) return(write(1, "\035\002", 2));
  5493.     if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
  5494. #endif
  5495. #ifndef SVORPOSIX            /* BSD, V7, etc */
  5496.     cccbrk.sg_flags |= CBREAK;          /* Set to character wakeup, */
  5497.     cccbrk.sg_flags &= ~ECHO;           /* no echo. */
  5498.     x = stty(0,&cccbrk);
  5499. #else                    /* Sys V and POSIX */
  5500. #ifndef OXOS
  5501.     cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
  5502. #else /* OXOS */
  5503.     cccbrk.c_lflag &= ~(ICANON|ECHO);
  5504.     cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
  5505. #endif /* OXOS */
  5506. #ifndef VINTR
  5507.     cccbrk.c_cc[0] = 003;               /* interrupt char is control-c */
  5508. #else
  5509.     cccbrk.c_cc[VINTR] = 003;
  5510. #endif /* VINTR */
  5511. #ifndef VQUIT
  5512.     cccbrk.c_cc[1] = escchr;            /* escape during packet modes */
  5513. #else
  5514.     cccbrk.c_cc[VQUIT] = escchr;
  5515. #endif /* VQUIT */
  5516. #ifndef VEOF
  5517.     cccbrk.c_cc[4] = 1;
  5518. #else
  5519. #ifndef OXOS
  5520. #ifdef VMIN
  5521.     cccbrk.c_cc[VMIN] = 1;
  5522. #endif /* VMIN */
  5523. #else /* OXOS */
  5524.     cccbrk.c_min = 1;
  5525. #endif /* OXOS */
  5526. #endif /* VEOF */
  5527. #ifdef ZILOG
  5528.     cccbrk.c_cc[5] = 0;
  5529. #else
  5530. #ifndef VEOL
  5531.     cccbrk.c_cc[5] = 1;
  5532. #else
  5533. #ifndef OXOS
  5534. #ifdef VTIME
  5535.     cccbrk.c_cc[VTIME] = 1;
  5536. #endif /* VTIME */
  5537. #else /* OXOS */
  5538.     cccbrk.c_time = 1;
  5539. #endif /* OXOS */
  5540. #endif /* VEOL */
  5541. #endif /* ZILOG */
  5542. #ifdef BSD44ORPOSIX            /* Set new modes */
  5543.     x = tcsetattr(0,TCSADRAIN,&cccbrk);
  5544. #else /* ATTSV */                  /* or the POSIX way */
  5545.     x = ioctl(0,TCSETAW,&cccbrk);    /* the Sys V way */
  5546. #endif /* BSD44ORPOSIX */
  5547. #endif /* SVORPOSIX */
  5548.  
  5549. #ifndef aegis
  5550. #ifndef NOSETBUF
  5551.     if (x > -1) setbuf(stdout,NULL);    /* Make console unbuffered. */
  5552. #endif /* NOSETBUF */
  5553. #endif /* aegis */
  5554.  
  5555. #ifdef  V7
  5556. #ifndef MINIX
  5557.     if (kmem[CON] < 0) {
  5558.         qaddr[CON] = initrawq(0);
  5559.         if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
  5560.             fprintf(stderr, "Can't read /dev/kmem in concb.\n");
  5561.             perror("/dev/kmem");
  5562.             exit(1);
  5563.         }
  5564.     }
  5565. #endif /* MINIX */
  5566. #endif /* V7 */
  5567.     debug(F101,"concb returns","",x);
  5568.     return(x);
  5569. }
  5570.  
  5571. /*  C O N B I N  --  Put console in binary mode  */
  5572.  
  5573. /*  Returns 0 if ok, -1 if not  */
  5574.  
  5575. int
  5576. #ifdef CK_ANSIC
  5577. conbin(char esc)
  5578. #else
  5579. conbin(esc) char esc;
  5580. #endif /* CK_ANSIC */
  5581. /* conbin */  {
  5582.     if (!isatty(0)) return(0);          /* only for real ttys */
  5583.     congm();                /* Get modes if necessary. */
  5584.     debug(F100,"conbin","",0);
  5585.     escchr = esc;                       /* Make this available to other fns */
  5586.     ckxech = 1;                         /* Program can echo characters */
  5587. #ifdef aegis
  5588.     conbufn = 0;
  5589.     if (concrp) return(write(1, "\035\002", 2));
  5590.     if (conuid == input_pad_$uid) {
  5591.     pad_$raw(ios_$stdin, st);
  5592.     return(0);
  5593.       }
  5594. #endif /* aegis */
  5595.  
  5596. #ifdef SVORPOSIX
  5597. #ifndef OXOS
  5598.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
  5599. #else /* OXOS */
  5600.     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
  5601.     ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
  5602. #endif /* OXOS */
  5603.     ccraw.c_iflag |= (BRKINT|IGNPAR);
  5604. #ifdef ATTSV
  5605. #ifdef BSD44
  5606.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
  5607.                         |INPCK|ISTRIP);
  5608. #else
  5609.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
  5610.                         |INPCK|ISTRIP);
  5611. #endif /* BSD44 */
  5612. #else /* POSIX */
  5613.     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
  5614. #endif /* ATTSV */
  5615.     ccraw.c_oflag &= ~OPOST;
  5616. #ifdef COMMENT
  5617. /*
  5618.   WHAT THE HECK WAS THIS FOR?
  5619.   The B9600 setting (obviously) prevents CONNECT from working at any
  5620.   speed other than 9600 when you are logged in to the 7300 on a serial
  5621.   line.  Maybe some of the other flags are necessary -- if so, put back
  5622.   the ones that are needed.  This code is supposed to work the same, no
  5623.   matter whether you are logged in to the 7300 on the real console device,
  5624.   or through a serial port.
  5625. */
  5626. #ifdef ATT7300
  5627.     ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
  5628. #endif /* ATT7300 */
  5629. #endif /* COMMENT */
  5630.  
  5631. /*** Kermit used to put the console in 8-bit raw mode, but some users have
  5632.  *** pointed out that this should not be done, since some sites actually
  5633.  *** use terminals with parity settings on their Unix systems, and if we
  5634.  *** override the current settings and stop doing parity, then their terminals
  5635.  *** will display blotches for characters whose parity is wrong.  Therefore,
  5636.  *** the following two lines are commented out (Larry Afrin, Clemson U):
  5637.  ***
  5638.  ***   ccraw.c_cflag &= ~(PARENB|CSIZE);
  5639.  ***   ccraw.c_cflag |= (CS8|CREAD);
  5640.  ***
  5641.  *** Sys III/V sites that have trouble with this can restore these lines.
  5642.  ***/
  5643. #ifndef VINTR
  5644.     ccraw.c_cc[0] = 003;        /* Interrupt char is Ctrl-C */
  5645. #else
  5646.     ccraw.c_cc[VINTR] = 003;
  5647. #endif /* VINTR */
  5648. #ifndef VQUIT
  5649.     ccraw.c_cc[1] = escchr;        /* Escape during packet mode */
  5650. #else
  5651.     ccraw.c_cc[VQUIT] = escchr;
  5652. #endif /* VQUIT */
  5653. #ifndef VEOF
  5654.     ccraw.c_cc[4] = 1;
  5655. #else
  5656. #ifndef OXOS
  5657. #ifdef VMIN
  5658.     ccraw.c_cc[VMIN] = 1;
  5659. #endif /* VMIN */
  5660. #else /* OXOS */
  5661.     ccraw.c_min = 1;
  5662. #endif /* OXOS */
  5663. #endif /* VEOF */
  5664.  
  5665. #ifdef ZILOG
  5666.     ccraw.c_cc[5] = 0;
  5667. #else
  5668. #ifndef VEOL
  5669.     ccraw.c_cc[5] = 1;
  5670. #else
  5671. #ifndef OXOS
  5672. #ifdef VTIME
  5673.     ccraw.c_cc[VTIME] = 1;
  5674. #endif /* VTIME */
  5675. #else /* OXOS */
  5676.     ccraw.c_time = 1;
  5677. #endif /* OXOS */
  5678. #endif /* VEOL */
  5679. #endif /* ZILOG */
  5680.  
  5681. #ifdef BSD44ORPOSIX
  5682.     return(tcsetattr(0,TCSADRAIN,&ccraw));
  5683. #else
  5684.     return(ioctl(0,TCSETAW,&ccraw));    /* Set new modes. */
  5685. #endif /* BSD44ORPOSIX */
  5686.  
  5687. #else /* Berkeley, etc. */
  5688.     ccraw.sg_flags |= (RAW|TANDEM);     /* Set rawmode, XON/XOFF (ha) */
  5689.     ccraw.sg_flags &= ~(ECHO|CRMOD);    /* Set char wakeup, no echo */
  5690.     return(stty(0,&ccraw));
  5691. #endif /* SVORPOSIX */
  5692. }
  5693.  
  5694.  
  5695. /*  C O N R E S  --  Restore the console terminal  */
  5696.  
  5697. int
  5698. conres() {
  5699.     debug(F101,"conres cgmf","",cgmf);
  5700.     if (cgmf < 1) return(0);        /* Do nothing if modes unchanged */
  5701.     if (!isatty(0)) return(0);          /* only for real ttys */
  5702.     debug(F100,"conres isatty ok","",0);
  5703.     ckxech = 0;                         /* System should echo chars */
  5704.  
  5705. #ifdef aegis
  5706.     conbufn = 0;
  5707.     if (concrp) return(write(1, "\035\001", 2));
  5708.     if (conuid == input_pad_$uid) {
  5709.     pad_$cooked(ios_$stdin, st);
  5710.     return(0);
  5711.     }
  5712. #endif /* aegis */
  5713.  
  5714. #ifdef BSD44ORPOSIX
  5715.     debug(F100,"conres restoring tcsetattr","",0);
  5716.     return(tcsetattr(0,TCSADRAIN,&ccold));
  5717. #else
  5718. #ifdef ATTSV
  5719.     debug(F100,"conres restoring ioctl","",0);
  5720.     return(ioctl(0,TCSETAW,&ccold));
  5721. #else /* BSD, V7, and friends */
  5722. #ifdef sony_news            /* Sony NEWS */
  5723.     if (km_con != -1)
  5724.       ioctl(0,TIOCKSET,&km_con);    /* Restore console Kanji mode */
  5725. #endif /* sony_news */
  5726.     msleep(300);
  5727.     debug(F100,"conres restoring stty","",0);
  5728.     return(stty(0,&ccold));
  5729. #endif /* ATTSV */
  5730. #endif /* BSD44ORPOSIX */
  5731. }
  5732.  
  5733. /*  C O N O C  --  Output a character to the console terminal  */
  5734.  
  5735. int
  5736. #ifdef CK_ANSIC
  5737. conoc(char c)
  5738. #else
  5739. conoc(c) char c;
  5740. #endif /* CK_ANSIC */
  5741. /* conoc */ {
  5742.     return(write(1,&c,1));
  5743. }
  5744.  
  5745. /*  C O N X O  --  Write x characters to the console terminal  */
  5746.  
  5747. int
  5748. conxo(x,s) int x; char *s; {
  5749.     return(write(1,s,x));
  5750. }
  5751.  
  5752. /*  C O N O L  --  Write a line to the console terminal  */
  5753.  
  5754. int
  5755. conol(s) char *s; {
  5756.     int len;
  5757.     len = (int)strlen(s);
  5758.     return(write(1,s,len));
  5759. }
  5760.  
  5761. /*  C O N O L A  --  Write an array of lines to the console terminal */
  5762.  
  5763. int
  5764. conola(s) char *s[]; {
  5765.     int i;
  5766.     for (i=0 ; *s[i] ; i++) if (conol(s[i]) < 0) return(-1);;
  5767.     return(0);
  5768. }
  5769.  
  5770. /*  C O N O L L  --  Output a string followed by CRLF  */
  5771.  
  5772. int
  5773. conoll(s) char *s; {
  5774.     conol(s);
  5775.     return(write(1,"\r\n",2));
  5776. }
  5777.  
  5778. /*  C O N C H K  --  Return how many characters available at console  */
  5779.  
  5780. int
  5781. conchk() {
  5782.     int x; PEEKTYPE n;
  5783.  
  5784.     if (backgrd || !isatty(0)) return(0);
  5785. #ifndef OXOS
  5786. #ifdef BSD44
  5787.     x = ioctl(0, FIONREAD, &n);         /* 4.4 BSD */
  5788.     debug(F101,"4.4BSD conchk","",n);
  5789.     return((x < 0) ? 0 : n);
  5790. #else
  5791. #ifdef PROVX1
  5792.     x = ioctl(0, TIOCQCNT, &ttbuf);
  5793.     n = ttbuf.sg_ispeed & 0377;
  5794.     return((x < 0) ? 0 : n);
  5795. #else
  5796. #ifdef aegis
  5797.     if (conbufn > 0) return(conbufn);   /* use old count if nonzero */
  5798.  
  5799.     /* read in more characters */
  5800.     conbufn = ios_$get(ios_$stdin,
  5801.               ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
  5802.     if (st.all != status_$ok) conbufn = 0;
  5803.     conbufp = conbuf;
  5804.     return(conbufn);
  5805. #else
  5806. #ifdef V7
  5807. #ifdef MINIX
  5808.     return(0);
  5809. #else
  5810.     lseek(kmem[CON], (long) qaddr[CON], 0);
  5811.     x = read(kmem[CON], &n, sizeof(int));
  5812.     return((x == sizeof(int))? n: 0);
  5813. #endif /* MINIX */
  5814. #else
  5815. #ifdef SVORPOSIX
  5816.     if (conesc) {                       /* Escape typed */
  5817.         debug(F100,"conchk returns conesc","",conesc);
  5818.         conesc = 0;
  5819.         signal(SIGQUIT,esctrp);         /* Restore escape */
  5820.         return(1);
  5821.     }
  5822. #ifdef CK_POLL
  5823.     {
  5824.       struct pollfd con;
  5825.       int status;
  5826.  
  5827.       con.fd = 0;
  5828.       con.events = POLLIN;
  5829.       con.revents = 0;
  5830.       status = poll(&con, 1, 0);
  5831.       if ((status > 0) && (con.revents & POLLIN))
  5832.     return(1);
  5833.     }
  5834. #endif /* CK_POLL */
  5835.     return(0);
  5836. #else
  5837. #ifdef C70
  5838.     if (conesc) {                       /* Escape typed */
  5839.         conesc = 0;
  5840.         signal(SIGQUIT,esctrp);         /* Restore escape */
  5841.         return(1);
  5842.     }
  5843.     return(0);
  5844. #else
  5845. #ifdef FIONREAD
  5846. /*
  5847.   Reportedly, this can cause C-Kermit to be suspended on certain OS's,
  5848.   such as Olivetti X/OS, when called if Kermit is really in the background.
  5849.   Hence the change at the top of this routine to return 0 if the backgrd
  5850.   flag is set.
  5851. */
  5852.     x = ioctl(0, FIONREAD, &n);         /* BSD and maybe some others */
  5853.     debug(F101,"conchk","",n);
  5854.     return((x < 0) ? 0 : n);
  5855. #else
  5856.     return(0);                          /* Others can't do. */
  5857. #endif /* FIONREAD */
  5858. #endif /* C70 */
  5859. #endif /* SVORPOSIX */
  5860. #endif /* V7 */
  5861. #endif /* aegis */
  5862. #endif /* PROVX1 */
  5863. #endif /* BSD44 */
  5864. #else  /* OXOS */
  5865.     x = ioctl(0, FIONREAD, &n);
  5866.     debug(F101,"X/OS conchk","",n);
  5867.     return((x < 0) ? 0 : n);
  5868. #endif /* OXOS */
  5869. }
  5870.  
  5871. /*  C O N I N C  --  Get a character from the console  */
  5872. /*
  5873.   Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
  5874.   read.  Upon success, returns the character.  Upon failure, returns -1.
  5875.   A timed read that does not complete within the timeout period returns -1.
  5876. */
  5877. int
  5878. coninc(timo) int timo; {
  5879.     int n = 0; CHAR ch;
  5880.     int xx;
  5881. #ifdef aegis                /* Apollo Aegis only... */
  5882.     debug(F101,"coninc timo","",timo);
  5883.     fflush(stdout);
  5884.     if (conchk() > 0) {
  5885.     --conbufn;
  5886.     return(*conbufp++ & 0377);
  5887.     }
  5888. #endif /* aegis */
  5889.  
  5890.     if (timo <= 0 ) {                   /* Untimed, blocking read. */
  5891.     while (1) {            /* Keep trying till we get one. */
  5892.         n = read(0, &ch, 1);    /* Read a character. */
  5893.         if (n == 0) continue;    /* Shouldn't happen. */
  5894.         if (n > 0)            /* If read was successful, */
  5895.           return(ch & 0377);    /* return the character. */
  5896.  
  5897. /* Come here if read() returned an error. */
  5898.  
  5899.         debug(F101, "coninc(0) errno","",errno); /* Log the error. */
  5900. #ifndef OXOS
  5901. #ifdef SVORPOSIX
  5902. #ifdef CIE                             /* CIE Regulus has no EINTR symbol? */
  5903. #ifndef EINTR
  5904. #define EINTR 4
  5905. #endif /* EINTR */
  5906. #endif /* CIE */
  5907. /*
  5908.   This routine is used for several different purposes.  In CONNECT mode, it is
  5909.   used to do an untimed, blocking read from the keyboard in the lower CONNECT
  5910.   fork.  During local-mode file transfer, it reads a character from the
  5911.   console to interrupt the file transfer (like A for a status report, X to
  5912.   cancel a file, etc).  Obviously, we don't want the reads in the latter case
  5913.   to be blocking, or the file transfer would stop until the user typed
  5914.   something.  Unfortunately, System V does not allow the console device input
  5915.   buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
  5916.   used instead.  During local-mode file transfer, the SIGQUIT signal is armed
  5917.   and trapped by esctrp(), and this routine pretends to have read the quit
  5918.   character from the keyboard normally.  But, kludge or no kludge, the read()
  5919.   issued by this command, under System V only, can fail if a signal -- ANY
  5920.   signal -- is caught while the read is pending.  This can occur not only when
  5921.   the user types the quit character, but also during telnet negotiations, when
  5922.   the lower CONNECT fork signals the upper one about an echoing mode change.
  5923.   When this happens, we have to post the read() again.  This is apparently not
  5924.   a problem in BSD-based UNIX versions.
  5925. */
  5926.         if (errno == EINTR)        /* Read interrupted. */
  5927.           if (conesc)  {        /* If by SIGQUIT, */
  5928.           conesc = 0;        /* the conesc variable is set, */
  5929.           return(escchr);    /* so return the escape character. */
  5930.          } else continue;        /* By other signal, try again. */
  5931. #else
  5932. /*
  5933.   This might be dangerous, but let's do this on non-System V versions too,
  5934.   since at least one SunOS 4.1.2 user complains of immediate disconnections
  5935.   upon first making a TELNET connection.
  5936. */
  5937.         if (errno == EINTR)        /* Read interrupted. */
  5938.           continue;
  5939. #endif /* SVORPOSIX */
  5940. #else /* OXOS */
  5941.         if (errno == EINTR)        /* Read interrupted. */
  5942.           continue;
  5943. #endif /* OXOS */
  5944.         return(-1);            /* Error */
  5945.     }
  5946.     }
  5947.  
  5948.     if (timo <= 0)
  5949.       /* This should never happen */
  5950.       debug(F100,"coninc HORRIBLE ERROR","",0);
  5951.  
  5952. /* Timed read... */
  5953.  
  5954.     saval = signal(SIGALRM,timerh);    /* Set up timeout handler. */
  5955.     xx = alarm(timo);            /* Set the alarm. */
  5956.     debug(F101,"coninc alarm","",xx);
  5957.     if (setjmp(sjbuf))            /* The read() timed out. */
  5958.       n = -2;                /* Code for timeout. */
  5959.     else
  5960.       n = read(0, &ch, 1);
  5961.     ttimoff();                /* Turn off timer */
  5962.     if (n > 0)                /* Got character OK. */
  5963.       return(ch & 0377);        /* Return it. */
  5964.  
  5965. /*
  5966.   Read returned an error.  Same deal as above, but without the loop.
  5967. */
  5968.     debug(F101, "coninc(timo) n","",n);
  5969.     debug(F101, "coninc(timo) errno","",errno);
  5970. #ifndef OXOS
  5971. #ifdef SVORPOSIX
  5972.     if (n == -1 && errno == EINTR && conesc != 0) {
  5973.     conesc = 0;
  5974.     return(escchr);            /* User entered escape character. */
  5975.     } else                /* n == 0 shouldn't happen. */
  5976. #endif /* SVORPOSIX */
  5977. #endif /* ! OXOS */
  5978.       return(-1);
  5979. }
  5980.  
  5981. /*  C O N G K S  --  Console Get Keyboard Scancode  */
  5982.  
  5983. #ifndef congks
  5984. /*
  5985.   This function needs to be filled in with the various system-dependent
  5986.   system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
  5987.   keyboard scan code.  For now, it's a dummy.
  5988. */
  5989. int
  5990. congks(timo) int timo; {
  5991.     return(coninc(timo));
  5992. }
  5993. #endif /* congks */
  5994.  
  5995. #ifdef ATT7300
  5996.  
  5997. /*  A T T D I A L  --  Dial up the remote system using internal modem
  5998.  * Purpose: to open and dial a number on the internal modem available on the
  5999.  * ATT7300 UNIX PC.  Written by Joe Doupnik. Superceeds version written by
  6000.  * Richard E. Hill, Dickinson, TX. which employed dial(3c).
  6001.  * Uses information in <sys/phone.h> and our status int attmodem.
  6002.  */
  6003. attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
  6004.     char *telnum;
  6005.     int ttclos();
  6006.  
  6007.     attmodem &= ~ISMODEM;                       /* modem not in use yet */
  6008.                     /* Ensure O_NDELAY is set, else i/o traffic hangs */
  6009.                     /* We turn this flag off once the dial is complete */
  6010.     fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
  6011.  
  6012.     /* Condition line, check availability & DATA mode, turn on speaker */
  6013.     if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
  6014.         printf("cannot access phone\n");
  6015.         ttclos(0);
  6016.         return (-2);
  6017.     }
  6018.     ioctl(ttyfd,PIOCGETP,&dialer);      /* get phone dialer parameters */
  6019.  
  6020.     if (dialer.c_lineparam & VOICE) {    /* phone must be in DATA mode */
  6021.         printf(" Should not dial with modem in VOICE mode.\n");
  6022.         printf(" Exit Kermit, switch to DATA and retry call.\n");
  6023.         ttclos(0);
  6024.         return (-2);
  6025.     }
  6026. #ifdef ATTTONED                /* Old way, tone dialing only. */
  6027.     dialer.c_lineparam = DATA | DTMF;    /* Dial with tones, */
  6028.     dialer.c_lineparam &= ~PULSE;    /* not with pulses. */
  6029. #else
  6030.     /* Leave current pulse/tone state alone. */
  6031.     /* But what about DATA?  Add it back if you have trouble. */
  6032.     /* sys/phone says you get DATA automatically by opening device RDWR */
  6033. #endif
  6034.     dialer.c_waitdialtone = 5;                  /* wait 5 sec for dialtone */
  6035. #ifdef COMMENT
  6036.     dialer.c_feedback = SPEAKERON|NORMSPK|RINGON;  /* control speaker */
  6037. #else
  6038.     /* sys/phone says RINGON used only for incoming voice calls */
  6039.     dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
  6040.     dialer.c_feedback |= SPEAKERON|NORMSPK;
  6041. #endif
  6042.     dialer.c_waitflash = 500;                   /* 0.5 sec flash hook */
  6043.     if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) {   /* set phone parameters */
  6044.         printf("Cannot set modem characteristics\n");
  6045.         ttclos(0);
  6046.         return (-2);
  6047.     }
  6048.     ioctl(ttyfd,PIOCRECONN,0);        /* Turns on speaker for pulse */
  6049.  
  6050. #ifdef COMMENT
  6051.     fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
  6052. line_status:%o feedback:%o\n",
  6053.     dialer.c_lineparam, dialer.c_waitdialtone,
  6054.     dialer.c_linestatus, dialer.c_feedback);
  6055. #endif
  6056.  
  6057.     attmodem |= ISMODEM;                        /* modem is now in-use */
  6058.     sleep(1);
  6059.     for (telnum = telnbr; *telnum != '\0'; telnum++)    /* dial number */
  6060. #ifdef ATTTONED
  6061.       /* Tone dialing only */
  6062.       if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
  6063.       perror("Error in dialing");
  6064.       ttclos(0);
  6065.       return(-2);
  6066.       }
  6067. #else /* Allow Pulse or Tone dialing */
  6068.     switch (*telnum) {
  6069.       case 't': case 'T': case '%':    /* Tone dialing requested */
  6070.     dialer.c_lineparam |= DTMF;
  6071.     dialer.c_lineparam &= ~PULSE;
  6072.     if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
  6073.         printf("Cannot set modem to tone dialing\n");
  6074.         ttclos(0);
  6075.         return(-2);
  6076.     }
  6077.     break;
  6078.       case 'd': case 'D': case 'p': case 'P': case '^':
  6079.     dialer.c_lineparam |= PULSE;
  6080.     dialer.c_lineparam &= ~DTMF;
  6081.     if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
  6082.         printf("Cannot set modem to pulse dialing\n");
  6083.         ttclos(0);
  6084.         return(-2);
  6085.     }
  6086.     break;
  6087.       default:
  6088.         if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
  6089.         perror("Dialing error");
  6090.         ttclos(0);
  6091.         return(-2);
  6092.     }
  6093.     break;
  6094.     }
  6095. #endif
  6096.  
  6097.     ioctl(ttyfd,PIOCDIAL,"@");        /* terminator for data call */
  6098.     do {                /* wait for modems to Connect */
  6099.         if (ioctl(ttyfd,PIOCGETP,&dialer) != 0)    { /* get params */
  6100.         perror("Cannot get modems to connect");
  6101.         ttclos(0);
  6102.         return(-2);
  6103.     }
  6104.     } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
  6105.     /* Turn off O_NDELAY flag now. */
  6106.     fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
  6107.     signal(SIGHUP, ttclos);             /* hangup on loss of carrier */
  6108.     return(0);                          /* return success */
  6109. }
  6110.  
  6111. /*
  6112.   Offgetty, ongetty functions. These function get the 'getty(1m)' off
  6113.   and restore it to the indicated line.  Shell's return codes are:
  6114.     0: Can't do it.  Probably a user logged on.
  6115.     1: No need.  No getty on that line.
  6116.     2: Done, you should restore the getty when you're done.
  6117.   DOGETY System(3), however, returns them as 0, 256, 512, respectively.
  6118.   Thanks to Kevin O'Gorman, Anarm Software Systems.
  6119.  
  6120.    getoff.sh looks like:   geton.sh looks like:
  6121.      setgetty $1 0           setgetty $1 1
  6122.      err=$?                  exit $?
  6123.      sleep 2
  6124.      exit $err
  6125. */
  6126.  
  6127. /*  O F F G E T T Y  --  Turn off getty(1m) for the communications tty line
  6128.  * and get status so it can be restarted after the line is hung up.
  6129.  */
  6130. int
  6131. offgetty(ttname) char *ttname; {
  6132.     char temp[30];
  6133.     while (*ttname != '\0') ttname++;       /* seek terminator of path */
  6134.     ttname -= 3;                            /* get last 3 chars of name */
  6135.     sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
  6136.     return(zsyscmd(temp));
  6137. }
  6138.  
  6139. /*  O N G E T T Y  --  Turn on getty(1m) for the communications tty line */
  6140.  
  6141. int
  6142. ongetty(ttname) char *ttname; {
  6143.     char temp[30];
  6144.     while (*ttname != '\0') ttname++;       /* comms tty path name */
  6145.     ttname -= 3;
  6146.     sprintf(temp,"/usr/bin/geton.sh %s",ttname);
  6147.     return(zsyscmd(temp));
  6148. }
  6149. #endif /* ATT7300 */
  6150.  
  6151. /*  T T S C A R R  --  Set ttcarr variable, controlling carrier handling.
  6152.  *
  6153.  *  0 = Off: Always ignore carrier. E.g. you can connect without carrier.
  6154.  *  1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
  6155.  *  2 = Auto: For "modem direct": The same as "Off".
  6156.  *            For real modem types: Heed carrier during connect, but ignore
  6157.  *                it anytime else.  Compatible with pre-5A C-Kermit versions.
  6158.  *
  6159.  * As you can see, this setting does not affect dialing, which always ignores
  6160.  * carrier (unless there is some special exception for some modem type).  It
  6161.  * does affect ttopen() if it is set before ttopen() is used.  This setting
  6162.  * takes effect on the next call to ttopen()/ttpkt()/ttvt().  And they are
  6163.  * (or should be) always called before any communications is tried, which
  6164.  * means that, practically speaking, the effect is immediate.
  6165.  *
  6166.  * Of course, nothing of this applies to remote mode (xlocal = 0).
  6167.  *
  6168.  * Someone has yet to uncover how to manipulate the carrier in the BSD
  6169.  * environment (or any non-termio using environment).  Until that time, this
  6170.  * will simply be a no-op for BSD.
  6171.  *
  6172.  * Note that in previous versions, the carrier was most often left unchanged
  6173.  * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX.  This
  6174.  * has changed.  Now it is controlled by ttcarr in conjunction with these
  6175.  * modes.
  6176.  */
  6177. int
  6178. ttscarr(carrier) int carrier; {
  6179.     ttcarr = carrier;
  6180.     debug(F101, "ttscarr","",ttcarr);
  6181.     return(ttcarr);
  6182. }
  6183.  
  6184. /* C A R R C T L  --  Set tty modes for carrier treatment.
  6185.  *
  6186.  * Sets the appropriate bits in a termio or sgttyb struct for carrier control
  6187.  * (actually, there are no bits in sgttyb for that), or performs any other
  6188.  * operations needed to control this on the current system.  The function does
  6189.  * not do the actual TCSETA or stty, since often we want to set other bits too
  6190.  * first.  Don't call this function when xlocal is 0, or the tty is not opened.
  6191.  *
  6192.  * We don't know how to do anything like carrier control on non-ATTSV systems,
  6193.  * except, apparently, ultrix.  See above.  It is also known that this doesn't
  6194.  * have much effect on a Xenix system.  For Xenix, one should switch back and
  6195.  * forth between the upper and lower case device files.  Maybe later. 
  6196.  * Presently, Xenix will stick to the mode it was opened with.
  6197.  *
  6198.  * carrier: 0 = ignore carrier, 1 = require carrier.
  6199.  * The current state is saved in curcarr, and checked to save labour.
  6200.  */
  6201. #ifdef SVORPOSIX
  6202. int
  6203. #ifdef BSD44ORPOSIX
  6204. carrctl(ttpar, carrier)    struct termios *ttpar; int carrier;
  6205. #else /* ATTSV */
  6206. carrctl(ttpar, carrier)    struct termio *ttpar; int carrier;
  6207. #endif /* BSD44ORPOSIX */
  6208. /* carrctl */ {
  6209.     debug(F101, "carrctl","",carrier);
  6210.     if (carrier)
  6211.       ttpar->c_cflag &= ~CLOCAL;
  6212.     else
  6213.       ttpar->c_cflag |= CLOCAL;
  6214.     return(0);
  6215. }
  6216. #else /* Berkeley, V7, et al... */
  6217. int
  6218. carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
  6219.     debug(F101, "carrctl","",carrier);
  6220.     if (carrier == curcarr)
  6221.       return(0);
  6222.     curcarr = carrier;
  6223. #ifdef ultrix
  6224. #ifdef COMMENT
  6225. /*
  6226.   Old code from somebody at DEC that tends to get stuck, time out, etc.
  6227. */
  6228.     if (carrier) {
  6229.     ioctl(ttyfd, TIOCMODEM, &temp);
  6230.     ioctl(ttyfd, TIOCHPCL, 0);
  6231.     } else {
  6232.     /* (According to the manuals, TIOCNCAR should be preferred */
  6233.     /* over TIOCNMODEM...) */
  6234.     ioctl(ttyfd, TIOCNMODEM, &temp);
  6235.     }
  6236. #else
  6237. /*
  6238.   New code from Jamie Watson that, he says, eliminates the problems.
  6239. */
  6240.     if (carrier) {
  6241.     ioctl(ttyfd, TIOCCAR);
  6242.     ioctl(ttyfd, TIOCHPCL);
  6243.     } else {
  6244.     ioctl(ttyfd, TIOCNCAR);
  6245.     }
  6246. #endif /* COMMENT */
  6247. #endif /* ultrix */
  6248.     return(0);
  6249. }
  6250. #endif /* SVORPOSIX */
  6251.  
  6252.  
  6253. /*  T T G M D M  --  Get modem signals  */
  6254. /*
  6255.  Looks for RS-232 modem signals, and returns those that are on in as its
  6256.  return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
  6257.  Returns: 
  6258.  -3 Not implemented
  6259.  -2 if the communication device does not have modem control (e.g. telnet)
  6260.  -1 on error.
  6261.  >= 0 on success, with a bit mask containing the modem signals that are on.
  6262. */
  6263.  
  6264. /*
  6265.   Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
  6266.   modem control, namely the TIOCMGET ioctl.
  6267. */
  6268.  
  6269. #ifdef BSD43
  6270. #define K_MDMCTL
  6271. #endif
  6272.  
  6273. #ifdef SUNOS4
  6274. #define K_MDMCTL
  6275. #endif
  6276.  
  6277. #ifdef TIOCMGET
  6278. #define K_MDMCTL
  6279. #endif
  6280.  
  6281. int
  6282. ttgmdm() {
  6283.  
  6284. #ifdef HPUX                /* HPUX has its own way */
  6285.  
  6286. /*
  6287.   NOTE: I don't have an HPUX man page, and so I'm only guessing at the
  6288.   right names for these symbols.  Somebody with HPUX please let me know
  6289.   what corrections are needed.
  6290. */
  6291.  
  6292.     int x, y, z;
  6293.  
  6294.     if (netconn) return(-2);        /* No modem signals for network */
  6295.     if (xlocal)                /* Get modem signals */
  6296.       x = ioctl(ttyfd,MCGETA,&y);
  6297.     else
  6298.       x = ioctl(0,MCGETA,&y);
  6299.     if (x < 0) return(-1);
  6300.     debug(F101,"ttgmdm","",y);
  6301.  
  6302.     z = 0;                /* Initialize return value */
  6303.  
  6304. /* Now set bits for each modem signal that is reported to be on. */
  6305.  
  6306. #ifdef MCTS
  6307.     /* Clear To Send */
  6308.     if (y & MCTS) z |= BM_CTS;
  6309. #endif
  6310. #ifdef MDSR
  6311.     /* Data Set Ready */
  6312.     if (y & MDSR) z |= BM_DSR;
  6313. #endif
  6314. #ifdef MDCD
  6315.     /* Carrier */
  6316.     if (y & MDCD) z |= BM_DCD;
  6317. #endif
  6318. #ifdef MRNG
  6319.     /* Ring Indicate */
  6320.     if (y & MRNG) z |= BM_RNG;
  6321. #endif
  6322. #ifdef MDTR
  6323.     /* Data Terminal Ready */
  6324.     if (y & MDTR) z |= BM_DTR;
  6325. #endif
  6326. #ifdef MRTS
  6327.     /* Request To Send */
  6328.     if (y & MRTS) z |= BM_RTS;
  6329. #endif
  6330.     return(z);
  6331.  
  6332. #else /* ! HPUX */
  6333.  
  6334. #ifdef K_MDMCTL
  6335. /*
  6336.   Note, <sys/ttycom> might have already been included by by <sys/ioctl.h>.
  6337.   Hence the following ifndef on a symbol which is defined there.
  6338. */
  6339. #ifndef TIOCMGET
  6340. #include <sys/ttycom.h>
  6341. #endif /* TIOCMGET */
  6342.  
  6343.     int x, y, z;
  6344.  
  6345.     if (netconn) return(-2);        /* Network, no modem signals. */
  6346.     if (xlocal)
  6347.       x = ioctl(ttyfd,TIOCMGET,&y);    /* Get modem signals. */
  6348.     else
  6349.       x = ioctl(0,TIOCMGET,&y);
  6350.     if (x < 0) return(-1);
  6351.     debug(F101,"ttgmdm","",y);
  6352.  
  6353.     z = 0;                /* Initialize return value. */
  6354. #ifdef TIOCM_CTS
  6355.     /* Clear To Send */
  6356.     if (y & TIOCM_CTS) z |= BM_CTS;
  6357. #endif
  6358. #ifdef TIOCM_DSR
  6359.     /* Data Set Ready */
  6360.     if (y & TIOCM_DSR) z |= BM_DSR;
  6361. #endif
  6362. #ifdef TIOCM_CAR
  6363.     /* Carrier */
  6364.     if (y & TIOCM_CAR) z |= BM_DCD;
  6365. #endif
  6366. #ifdef TIOCM_RNG
  6367.     /* Ring Indicate */
  6368.     if (y & TIOCM_RNG) z |= BM_RNG;
  6369. #endif
  6370. #ifdef TIOCM_DTR
  6371.     /* Data Terminal Ready */
  6372.     if (y & TIOCM_DTR) z |= BM_DTR;
  6373. #endif
  6374. #ifdef TIOCM_RTS
  6375.     /* Request To Send */
  6376.     if (y & TIOCM_RTS) z |= BM_RTS;
  6377. #endif
  6378.     return(z);
  6379. #else
  6380.     if (netconn) return(-2);
  6381.     return(-3);
  6382.  
  6383. #endif /* K_MDMCTL */
  6384. #endif /* HPUX */
  6385. }
  6386.  
  6387. /*  P S U S P E N D  --  Put this process in the background.  */
  6388.  
  6389. /*
  6390.   Call with flag nonzero if suspending is allowed, zero if not allowed.
  6391.   Returns 0 on apparent success, -1 on failure (flag was zero, or
  6392.   kill() returned an error code.
  6393. */
  6394. int
  6395. psuspend(flag) int flag; {
  6396.  
  6397. #ifdef RTU
  6398.     extern int rtu_bug;
  6399. #endif /* RTU */
  6400.  
  6401.     if (flag == 0) return(-1);
  6402.  
  6403. #ifdef NOJC
  6404.     return(-1);
  6405. #else
  6406. #ifdef SIGTSTP
  6407. /*
  6408.   The big question here is whether job control is *really* supported.
  6409.   There's no way Kermit can know for sure.  The fact that SIGTSTP is
  6410.   defined does not guarantee the Unix kernel supports it, and the fact
  6411.   that the Unix kernel supports it doesn't guarantee that the user's
  6412.   shell (or other process that invoked Kermit) supports it.
  6413. */
  6414. #ifdef RTU
  6415.     rtu_bug = 1;
  6416. #endif /* RTU */
  6417.     if (kill(0,SIGSTOP) < 0
  6418. #ifdef MIPS
  6419. /* Let's try this for MIPS too. */
  6420.     && kill(getpid(),SIGSTOP) < 0
  6421. #endif /* MIPS */
  6422.     ) {                /* If job control, suspend the job */
  6423.     perror("suspend");
  6424.     debug(F101,"psuspend error","",errno);
  6425.     return(-1);
  6426.     }
  6427.     debug(F100,"psuspend ok","",0);
  6428.     return(0);
  6429. #else
  6430.     return(-1);
  6431. #endif /* SIGTSTP */
  6432. #endif /* NOJC */
  6433. }
  6434.  
  6435. /*
  6436.   setuid package, by Kristoffer Eriksson, with contributions from Dean
  6437.   Long and fdc.
  6438. */
  6439.  
  6440. #ifndef _POSIX_SOURCE
  6441. #ifndef SUNOS4
  6442. #ifndef NEXT
  6443. #ifndef PS2AIX10
  6444. extern UID_T getuid(), geteuid(), getreuid();
  6445. extern GID_T getgid(), getegid(), getregid();
  6446. #endif /* PS2AIX10 */
  6447. #endif /* NEXT */
  6448. #endif /* SUNOS4 */
  6449. #endif /* _POSIX_SOURCE */
  6450.  
  6451. /*
  6452. Subject: Set-user-id
  6453. To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
  6454. Date: Sat, 21 Apr 90 4:48:25 MES
  6455. From: Kristoffer Eriksson <ske@pkmab.se>
  6456.  
  6457. This is a set of functions to be used in programs that may be run set-user-id
  6458. and/or set-group-id. They handle both the case where the program is not run
  6459. with such privileges (nothing special happens then), and the case where one
  6460. or both of these set-id modes are used.  The program is made to run with the
  6461. user's real user and group ids most of the time, except for when more
  6462. privileges are needed.  Don't set-user-id to "root".
  6463.  
  6464. This works on System V and POSIX.  In BSD, it depends on the
  6465. "saved-set-user-id" feature.
  6466. */
  6467.  
  6468. #define UID_ROOT 0            /* Root user and group ids */
  6469. #define GID_ROOT 0
  6470.  
  6471. /*
  6472.   The following construction automatically defines the symbol SETREUID for
  6473.   Unix versions based on Berkeley Unix 4.2 or later.  If this symbol is 
  6474.   defined, then this program will use getreuid() and getregid() calls in
  6475.   preference to getuid() and getgid(), which in Berkeley-based Unixes do
  6476.   not allow arbitrary switching back and forth of real & effective uid.
  6477.   This construction also allows -DSETREUID to be put on the cc command line
  6478.   for any system that has and wants to use setre[ug]id().  It also prevents
  6479.   automatic definition of SETREUID if -DNOSETREU is included on the cc 
  6480.   command line (or otherwise defined).
  6481. */
  6482. #ifdef FT18                /* None of this for Fortune. */
  6483. #define NOSETREU
  6484. #endif /* FT18 */
  6485.  
  6486. #ifdef ANYBSD
  6487. #ifndef BSD29
  6488. #ifndef BSD41
  6489. #ifndef SETREUID
  6490. #ifndef NOSETREU
  6491. #define SETREUID
  6492. #endif /* NOSETREU */                   
  6493. #endif /* SETREUID */
  6494. #endif /* !BSD41 */
  6495. #endif /* !BSD29 */
  6496. #endif /* ANYBSD */
  6497.  
  6498. /* Variables for user and group IDs. */
  6499.  
  6500. static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
  6501. static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
  6502.  
  6503.  
  6504. /* P R I V _ I N I  --  Initialize privileges package  */
  6505.  
  6506. /* Called as early as possible in a set-uid or set-gid program to store the
  6507.  * set-to uid and/or gid and step down to the users real uid and gid. The
  6508.  * stored id's can be temporarily restored (allowed in System V) during
  6509.  * operations that require the privilege.  Most of the time, the program
  6510.  * should execute in unpriviliged state, to not impose any security threat.
  6511.  *
  6512.  * Note: Don't forget that access() always uses the real id:s to determine
  6513.  * file access, even with privileges restored.
  6514.  *
  6515.  * Returns an error mask, with error values or:ed together:
  6516.  *   1 if setuid() fails,
  6517.  *   2 if setgid() fails, and
  6518.  *   4 if the program is set-user-id to "root", which can't be handled.
  6519.  *
  6520.  * Only the return value 0 indicates real success. In case of failure,
  6521.  * those privileges that could be reduced have been, at least, but the
  6522.  * program should be aborted none-the-less.
  6523.  *
  6524.  * Also note that these functions do not expect the uid or gid to change
  6525.  * without their knowing. It may work if it is only done temporarily, but
  6526.  * you're on your own.
  6527.  */
  6528. int
  6529. priv_ini() {
  6530.     int err = 0;
  6531.  
  6532.     /* Save real ID:s. */
  6533.     realuid = getuid();
  6534.     realgid = getgid();
  6535.  
  6536.     /* Save current effective ID:s, those set to at program exec. */
  6537.     privuid = geteuid();
  6538.     privgid = getegid();
  6539.  
  6540.     /* If running set-uid, go down to real uid, otherwise remember that
  6541.      * no privileged uid is available.
  6542.      *
  6543.      * Exceptions:
  6544.      *
  6545.      * 1) If the real uid is already "root" and the set-uid uid (the
  6546.      * initial effective uid) is not "root", then we would have trouble
  6547.      * if we went "down" to "root" here, and then temporarily back to the
  6548.      * set-uid uid (not "root") and then again tried to become "root". I
  6549.      * think the "saved set-uid" is lost when changing uid from effective
  6550.      * uid "root", which changes all uid, not only the effective uid. But
  6551.      * in this situation, we can simply go to "root" and stay there all
  6552.      * the time. That should give sufficient privilege (understatement!),
  6553.      * and give the right uids for subprocesses.
  6554.      *
  6555.      * 2) If the set-uid (the initial effective uid) is "root", and we
  6556.      * change uid to the real uid, we can't change it back to "root" when
  6557.      * we need the privilege, for the same reason as in 1). Thus, we can't
  6558.      * handle programs that are set-user-id to "root" at all. The program
  6559.      * should be aborted. Use some other uid. "root" is probably to
  6560.      * privileged for such things, anyway. (The uid is reverted to the
  6561.      * real uid until abortion.)
  6562.      *
  6563.      * These two exceptions have the effect that the "root" uid will never
  6564.      * be one of the two uids that are being switched between, which also
  6565.      * means we don't have to check for such cases in the switching
  6566.      * functions.
  6567.      *
  6568.      * Note that exception 1) is handled by these routines (by constantly
  6569.      * running with uid "root", while exception 2) is a serious error, and
  6570.      * is not provided for at all in the switching functions.
  6571.      */
  6572.     if (realuid == privuid)
  6573.     privuid = (UID_T) -1;        /* Not running set-user-id. */
  6574.  
  6575.     /* If running set-gid, go down to real gid, otherwise remember that
  6576.      * no privileged gid is available.
  6577.      *
  6578.      * There are no exception like there is for the user id, since there
  6579.      * is no group id that is privileged in the manner of uid "root".
  6580.      * There could be equivalent problems for group changing if the
  6581.      * program sometimes ran with uid "root" and sometimes not, but
  6582.      * that is already avoided as explained above.
  6583.      *
  6584.      * Thus we can expect always to be able to switch to the "saved set-
  6585.      * gid" when we want, and back to the real gid again. You may also
  6586.      * draw the conclusion that set-gid provides for fewer hassles than
  6587.      * set-uid.
  6588.      */
  6589.  
  6590.     if (realgid == privgid)        /* If not running set-user-id, */
  6591.       privgid = (GID_T) -1;        /*  remember it this way. */
  6592.  
  6593.     err = priv_off();            /* Turn off setuid privilege. */
  6594.  
  6595.     if (privuid == UID_ROOT)        /* If setuid to root, */
  6596.       err |= 4;                /* return this error. */
  6597.  
  6598.     if (realuid == UID_ROOT)        /* If real id is root, */
  6599.       privuid = (UID_T) -1;        /* stay root at all times. */
  6600.  
  6601.     return(err);
  6602. }
  6603.  
  6604.  
  6605. /* Macros for hiding the differences in UID/GID setting between various Unix
  6606.  * systems. These macros should always be called with both the privileged ID
  6607.  * and the non-privileged ID. The one in the second argument, will become the
  6608.  * effective ID. The one in the first argument will be retained for later
  6609.  * retrieval.
  6610.  */
  6611. #ifdef SETREUID
  6612. #ifdef SAVEDUID
  6613. /* On BSD systems with the saved-UID feature, we just juggle the effective
  6614.  * UID back and forth, and leave the real UID at its true value.  The kernel
  6615.  * allows switching to both the current real UID, the effective UID, and the
  6616.  * UID which the program is set-UID to.  The saved set-UID always holds the
  6617.  * privileged UID for us, and the real UID will always be the non-privileged,
  6618.  * and we can freely choose one of them for the effective UID at any time.
  6619.  */
  6620. #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
  6621. #define switchgid(hidden,active) setregid( (GID_T) -1, active)
  6622.  
  6623. #else   /* SETREUID,!SAVEDUID */
  6624.  
  6625. /* On systems with setreXid() but without the saved-UID feature, notably
  6626.  * BSD 4.2, we swap the real and effective UIDs each time.  It's
  6627.  * the effective UID that we are interrested in, but we have to retain the
  6628.  * unused UID somewhere to enable us to restore it later, and that we do this
  6629.  * in the real UID.  The kernel only allows switching to either the current 
  6630.  * real or the effective UID, unless you're "root".
  6631.  */
  6632. #define switchuid(hidden,active)    setreuid(hidden,active)
  6633. #define switchgid(hidden,active)    setregid(hidden,active)
  6634. #endif
  6635.  
  6636. #else /* !SETREUID, !SAVEDUID */
  6637.  
  6638. /* On System V and POSIX, the only thing we can change is the effective UID
  6639.  * (unless the current effective UID is "root", but initsuid() avoids that for
  6640.  * us).  The kernel allows switching to the current real UID or to the saved
  6641.  * set-UID.  These are always set to the non-privileged UID and the privileged
  6642.  * UID, respectively, and we only change the effective UID.  This breaks if
  6643.  * the current effective UID is "root", though, because for "root" setuid/gid
  6644.  * becomes more powerful, which is why initsuid() treats "root" specially.
  6645.  * Note: That special treatment maybe could be ignored for BSD?  Note: For
  6646.  * systems that don't fit any of these three cases, we simply can't support
  6647.  * set-UID.
  6648.  */
  6649. #define switchuid(hidden,active)    setuid(active)
  6650. #define switchgid(hidden,active)    setgid(active)
  6651. #endif /* SETREUID */
  6652.   
  6653.  
  6654. /* P R I V _ O N  --  Turn on the setuid and/or setgid */
  6655.  
  6656. /* Go to the privileged uid (gid) that the program is set-user-id
  6657.  * (set-group-id) to, unless the program is running unprivileged.
  6658.  * If setuid() fails, return value will be 1. If getuid() fails it
  6659.  * will be 2.  Return immediately after first failure, and the function
  6660.  * tries to restore any partial work done.  Returns 0 on success.
  6661.  * Group id is changed first, since it is less serious than user id.
  6662.  */
  6663. int
  6664. priv_on() {
  6665.     if (privgid != (GID_T) -1)
  6666.       if (switchgid(realgid,privgid))
  6667.         return(2);
  6668.  
  6669.     if (privuid != (UID_T) -1)
  6670.       if (switchuid(realuid,privuid)) {
  6671.       if (privgid != (GID_T) -1)
  6672.         switchgid(privgid,realgid);
  6673.       return(1);
  6674.       }
  6675.     return(0);
  6676. }
  6677.  
  6678. /* P R I V _ O F F  --  Turn on the real uid and gid */
  6679.  
  6680. /* Return to the unprivileged uid (gid) after an temporary visit to
  6681.  * privileged status, unless the program is running without set-user-id
  6682.  * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
  6683.  * in setgid() or:ed together. The functions tries to return both uid
  6684.  * and gid to unprivileged state, regardless of errors. Returns 0 on
  6685.  * success.
  6686.  */
  6687. int
  6688. priv_off() {
  6689.     int err = 0;
  6690.  
  6691.     if (privuid != (UID_T) -1)
  6692.        if (switchuid(privuid,realuid))
  6693.       err |= 1;
  6694.  
  6695.     if (privgid != (GID_T) -1)
  6696.        if (switchgid(privgid,realgid))
  6697.     err |= 2;
  6698.  
  6699.     return(err);
  6700. }
  6701.  
  6702. /* Turn off privilege permanently.  No going back.  This is necessary before
  6703.  * a fork() on BSD43 machines that don't save the setUID or setGID, because
  6704.  * we swap the real and effective ids, and we don't want to let the forked
  6705.  * process swap them again and get the privilege back. It will work on other
  6706.  * machines too, such that you can rely on its effect always being the same,
  6707.  * for instance, even when you're in priv_on() state when this is called.
  6708.  * (Well, that part about "permanent" is on System V only true if you follow
  6709.  * this with a call to exec(), but that's what we want it for anyway.)
  6710.  * Added by Dean Long -- dlong@midgard.ucsc.edu
  6711.  */
  6712. int
  6713. priv_can() {
  6714.  
  6715. #ifdef SETREUID
  6716.     int err = 0;
  6717.     if (privuid != (UID_T) -1)
  6718.        if (setreuid(realuid,realuid))
  6719.       err |= 1;
  6720.  
  6721.     if (privgid != (GID_T) -1)
  6722.         if (setregid(realgid,realgid))
  6723.        err |= 2;
  6724.  
  6725.     return(err);
  6726.  
  6727. #else
  6728.     /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
  6729.     return(priv_off());
  6730.  
  6731. #endif /* SETREUID */
  6732. }
  6733.  
  6734. /* P R I V _ O P N  --  For opening protected files or devices. */
  6735.  
  6736. int
  6737. priv_opn(name, modes) char *name; int modes; {
  6738.     int x;
  6739.     priv_on();                /* Turn privileges on */
  6740.     x = open(name, modes);        /* Try to open the device */
  6741.     priv_off();                /* Turn privileges off */
  6742.     return(x);                /* Return open's return code */
  6743. }
  6744.  
  6745. /*  P R I V _ C H K  --  Check privileges.  */
  6746.  
  6747. /*  Try to turn them off.  If turning them off did not succeed, cancel them */
  6748.  
  6749. int
  6750. priv_chk() {
  6751.     int x, y = 0;
  6752.     x = priv_off();            /* Turn off privs. */
  6753.     if (x != 0 || getuid() == privuid || geteuid() == privuid)
  6754.       y = priv_can();
  6755.     if (x != 0 || getgid() == privgid || getegid() == privgid)
  6756.       y = y | priv_can();
  6757.     return(y);
  6758. }
  6759.  
  6760. UID_T
  6761. real_uid() {
  6762.     return(realuid);
  6763. }
  6764.  
  6765. VOID
  6766. ttimoff() {                /* Turn off any timer interrupts */
  6767.     int xx;
  6768. /*
  6769.   As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
  6770.   SIG_DFL (to catch alarms, or if there is no handler, to exit).  This is to
  6771.   cure (mask, really) a deeper problem with stray alarms that occurs on some
  6772.   systems, possibly having to do with sleep(), that caused core dumps.  It
  6773.   should be OK to do this, because no code in this module uses nested alarms.
  6774.   (But we still have to watch out for SCRIPT and DIAL...)
  6775. */
  6776.     xx = alarm(0);
  6777.     /* debug(F101,"ttimoff alarm","",xx); */
  6778.     if (saval) {            /* Restore any previous */
  6779.     signal(SIGALRM,saval);        /* alarm handler. */
  6780.     /* debug(F101,"ttimoff alarm restoring saval","",saval); */
  6781.     saval = NULL;
  6782.     } else {
  6783.     signal(SIGALRM,SIG_IGN);    /* Used to be SIG_DFL */
  6784.     /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
  6785.     }
  6786. }
  6787.  
  6788. #ifdef OXOS
  6789. #undef kill
  6790. #endif /* OXOS */
  6791.  
  6792. #ifdef OXOS
  6793. int
  6794. priv_kill(pid, sig) int pid, sig; {
  6795.     int    i;
  6796.  
  6797.     if (priv_on())
  6798.     debug(F100,"priv_kill priv_on failed","",0);
  6799.     i = kill(pid, sig);
  6800.     if (priv_off())
  6801.     debug(F100,"priv_kill priv_off failed","",0);
  6802.     return(i);
  6803. }
  6804. #endif /* OXOS */
  6805.